Commit 3be79a142f7defc99d3fbca113f5c42fca31295b
Committed by
Moritz Wirger
1 parent
ca79b6c2
Add documentation for TimePattern.
Showing
5 changed files
with
234 additions
and
33 deletions
include/hueplusplus/Hue.h
include/hueplusplus/TimePattern.h
| @@ -27,26 +27,74 @@ | @@ -27,26 +27,74 @@ | ||
| 27 | 27 | ||
| 28 | namespace hueplusplus | 28 | namespace hueplusplus |
| 29 | { | 29 | { |
| 30 | +//! \brief Namespace for time/date related classes and functions | ||
| 30 | namespace time | 31 | namespace time |
| 31 | { | 32 | { |
| 33 | +//! \brief Converts a time_point to a timestamp string | ||
| 34 | +//! \param time Time to convert | ||
| 35 | +//! \returns Date and time in the format | ||
| 36 | +//! <code>YYYY-MM-DD</code><strong>T</strong><code>hh:mm:ss</code>. | ||
| 37 | +//! | ||
| 38 | +//! Returns the time in the local time zone. | ||
| 39 | +//! \throws HueException when time could not be converted | ||
| 32 | std::string timepointToTimestamp(std::chrono::system_clock::time_point time); | 40 | std::string timepointToTimestamp(std::chrono::system_clock::time_point time); |
| 41 | + | ||
| 42 | +//! \brief Converts a timestamp to a time_point | ||
| 43 | +//! \param timestamp Timestamp from the local time zone in the format | ||
| 44 | +//! <code>YYYY-MM-DD</code><strong>T</strong><code>hh:mm:ss</code> | ||
| 45 | +//! \returns time_point of the local system clock | ||
| 46 | +//! \throws std::invalid_argument when integer conversion fails | ||
| 47 | +//! \throws HueException when time cannot be represented as time_point | ||
| 33 | std::chrono::system_clock::time_point parseTimestamp(const std::string& timestamp); | 48 | std::chrono::system_clock::time_point parseTimestamp(const std::string& timestamp); |
| 34 | 49 | ||
| 50 | +//! \brief Converts duration to a time string | ||
| 51 | +//! \param duration Duration or time of day to format. Must be less than 24 hours | ||
| 52 | +//! \returns Duration string in the format <code>hh:mm:ss</code> | ||
| 53 | +//! \throws HueException when \c duration longer than 24 hours. | ||
| 35 | std::string durationTo_hh_mm_ss(std::chrono::system_clock::duration duration); | 54 | std::string durationTo_hh_mm_ss(std::chrono::system_clock::duration duration); |
| 55 | + | ||
| 56 | +//! \brief Converts time string to a duration | ||
| 57 | +//! \param hourMinSec Time/duration in the format <code>hh:mm:ss</code> | ||
| 58 | +//! \returns Duration (hours, minutes and seconds) from the string | ||
| 59 | +//! \throws std::invalid_argument when integer conversion fails | ||
| 36 | std::chrono::system_clock::duration parseDuration(const std::string& hourMinSec); | 60 | std::chrono::system_clock::duration parseDuration(const std::string& hourMinSec); |
| 37 | 61 | ||
| 62 | +//! \brief One-time, absolute time point with possible random variation | ||
| 63 | +//! | ||
| 64 | +//! Can be either used to represent a specific date and time, | ||
| 65 | +//! or a date and time with a random variation. | ||
| 38 | class AbsoluteTime | 66 | class AbsoluteTime |
| 39 | { | 67 | { |
| 40 | using clock = std::chrono::system_clock; | 68 | using clock = std::chrono::system_clock; |
| 41 | 69 | ||
| 42 | public: | 70 | public: |
| 71 | + //! \brief Create absolute time point | ||
| 72 | + //! \param baseTime Absolute time point | ||
| 73 | + //! \param variation Random variation, optional. When not zero, the time is randomly chosen between | ||
| 74 | + //! <code>baseTime - variation</code> and <code>baseTime + variation</code> | ||
| 43 | explicit AbsoluteTime(clock::time_point baseTime, clock::duration variation = std::chrono::seconds(0)); | 75 | explicit AbsoluteTime(clock::time_point baseTime, clock::duration variation = std::chrono::seconds(0)); |
| 44 | 76 | ||
| 77 | + //! \brief Get base time point | ||
| 78 | + //! | ||
| 79 | + //! Can be used for calculation with other system_clock time_points | ||
| 45 | clock::time_point getBaseTime() const; | 80 | clock::time_point getBaseTime() const; |
| 81 | + | ||
| 82 | + //! \brief Get random variation or zero | ||
| 83 | + //! | ||
| 84 | + //! The time can vary up to this amount in both directions. | ||
| 46 | clock::duration getRandomVariation() const; | 85 | clock::duration getRandomVariation() const; |
| 47 | 86 | ||
| 87 | + //! \brief Get formatted string as expected by Hue API | ||
| 88 | + //! \returns when variation is 0: Timestamp in the format | ||
| 89 | + //! <code>YYYY-MM-DD</code><strong>T</strong><code>hh:mm:ss</code> | ||
| 90 | + //! \returns when there is variation: Timestamp in the format | ||
| 91 | + //! <code>YYYY-MM-DD</code><strong>T</strong><code>hh:mm:ss</code><strong>A</strong><code>hh:mm:ss</code> | ||
| 92 | + //! with base time first, variation second | ||
| 48 | std::string toString() const; | 93 | std::string toString() const; |
| 49 | 94 | ||
| 95 | + //! \brief Parse AbsoluteTime from formatted string | ||
| 96 | + //! \param s Timestamp in the same format as returned by \ref toString() | ||
| 97 | + //! \returns AbsoluteTime with base time and variation from \c s | ||
| 50 | static AbsoluteTime parse(const std::string& s); | 98 | static AbsoluteTime parse(const std::string& s); |
| 51 | 99 | ||
| 52 | private: | 100 | private: |
| @@ -54,57 +102,113 @@ private: | @@ -54,57 +102,113 @@ private: | ||
| 54 | clock::duration variation; | 102 | clock::duration variation; |
| 55 | }; | 103 | }; |
| 56 | 104 | ||
| 105 | +//! \brief Any number of days of the week | ||
| 106 | +//! | ||
| 107 | +//! Can be used to represent weekly repetitions only on certain days. | ||
| 57 | class Weekdays | 108 | class Weekdays |
| 58 | { | 109 | { |
| 59 | public: | 110 | public: |
| 111 | + //! \brief Create with no days | ||
| 60 | Weekdays() : bitmask(0) {} | 112 | Weekdays() : bitmask(0) {} |
| 113 | + //! \brief Create with the day \c num | ||
| 114 | + //! \param num Day of the week, from monday (0) to sunday (6) | ||
| 61 | explicit Weekdays(int num) : bitmask(1 << num) {} | 115 | explicit Weekdays(int num) : bitmask(1 << num) {} |
| 62 | 116 | ||
| 117 | + //! \brief Check if no days are set | ||
| 63 | bool isNone() const; | 118 | bool isNone() const; |
| 119 | + //! \brief Check if all days are set | ||
| 64 | bool isAll() const; | 120 | bool isAll() const; |
| 121 | + //! \brief Check if Monday is contained | ||
| 65 | bool isMonday() const; | 122 | bool isMonday() const; |
| 123 | + //! \brief Check if Tuesday is contained | ||
| 66 | bool isTuesday() const; | 124 | bool isTuesday() const; |
| 125 | + //! \brief Check if Wednesday is contained | ||
| 67 | bool isWednesday() const; | 126 | bool isWednesday() const; |
| 127 | + //! \brief Check if Thursday is contained | ||
| 68 | bool isThursday() const; | 128 | bool isThursday() const; |
| 129 | + //! \brief Check if Friday is contained | ||
| 69 | bool isFriday() const; | 130 | bool isFriday() const; |
| 131 | + //! \brief Check if Saturday is contained | ||
| 70 | bool isSaturday() const; | 132 | bool isSaturday() const; |
| 133 | + //! \brief Check if Sunday is contained | ||
| 71 | bool isSunday() const; | 134 | bool isSunday() const; |
| 72 | 135 | ||
| 136 | + //! \brief Create set union with other Weekdays | ||
| 137 | + //! \param other Second set of days to combine with | ||
| 138 | + //! \returns A set of days containing all days of either \c this or \c other | ||
| 73 | Weekdays unionWith(Weekdays other) const; | 139 | Weekdays unionWith(Weekdays other) const; |
| 140 | + //! \brief Create set union with other Weekdays | ||
| 141 | + //! \see unionWith | ||
| 74 | Weekdays operator|(Weekdays other) const { return unionWith(other); } | 142 | Weekdays operator|(Weekdays other) const { return unionWith(other); } |
| 75 | 143 | ||
| 144 | + //! \brief Create a formatted, numeric string | ||
| 145 | + //! \returns A three digit code for the days as a bitmask | ||
| 76 | std::string toString() const; | 146 | std::string toString() const; |
| 77 | 147 | ||
| 148 | + //! \brief Creates an empty Weekdays | ||
| 78 | static Weekdays none(); | 149 | static Weekdays none(); |
| 150 | + //! \brief Creates set of all days | ||
| 79 | static Weekdays all(); | 151 | static Weekdays all(); |
| 152 | + //! \brief Creates Monday | ||
| 80 | static Weekdays monday(); | 153 | static Weekdays monday(); |
| 154 | + //! \brief Creates Tuesday | ||
| 81 | static Weekdays tuesday(); | 155 | static Weekdays tuesday(); |
| 156 | + //! \brief Creates Wednesday | ||
| 82 | static Weekdays wednesday(); | 157 | static Weekdays wednesday(); |
| 158 | + //! \brief Creates Thursday | ||
| 83 | static Weekdays thursday(); | 159 | static Weekdays thursday(); |
| 160 | + //! \brief Creates Friday | ||
| 84 | static Weekdays friday(); | 161 | static Weekdays friday(); |
| 162 | + //! \brief Creates Saturday | ||
| 85 | static Weekdays saturday(); | 163 | static Weekdays saturday(); |
| 164 | + //! \brief Creates Sunday | ||
| 86 | static Weekdays sunday(); | 165 | static Weekdays sunday(); |
| 87 | 166 | ||
| 167 | + //! \brief Parse from three digit code | ||
| 168 | + //! \param s Bitmask of days as a string | ||
| 169 | + //! \returns Parsed set of weekdays | ||
| 88 | static Weekdays parse(const std::string& s); | 170 | static Weekdays parse(const std::string& s); |
| 89 | 171 | ||
| 172 | + //! \brief Check whether all days are equal | ||
| 90 | bool operator==(const Weekdays& other) const { return bitmask == other.bitmask; } | 173 | bool operator==(const Weekdays& other) const { return bitmask == other.bitmask; } |
| 174 | + //! \brief Check whether not all days are equal | ||
| 91 | bool operator!=(const Weekdays& other) const { return bitmask != other.bitmask; } | 175 | bool operator!=(const Weekdays& other) const { return bitmask != other.bitmask; } |
| 92 | 176 | ||
| 93 | private: | 177 | private: |
| 94 | int bitmask; | 178 | int bitmask; |
| 95 | }; | 179 | }; |
| 96 | 180 | ||
| 181 | +//! \brief Time repeated weekly to daily, with possible random variation. | ||
| 182 | +//! | ||
| 183 | +//! Can be used to represent a time on one or multiple days per week. | ||
| 184 | +//! It can also have a random variation of up to 12 hours. | ||
| 97 | class RecurringTime | 185 | class RecurringTime |
| 98 | { | 186 | { |
| 99 | using clock = std::chrono::system_clock; | 187 | using clock = std::chrono::system_clock; |
| 100 | 188 | ||
| 101 | public: | 189 | public: |
| 190 | + //! \brief Create recurring time | ||
| 191 | + //! \param daytime Time of day, duration from the start of the day. | ||
| 192 | + //! \param days Days to repeat on, should not be Weekdays::none() | ||
| 193 | + //! \param variation Random variation, optional. Must be less than 12 hours. When not zero, the time is randomly | ||
| 194 | + //! chosen between <code>daytime - variation</code> and <code>daytime + variation</code> | ||
| 102 | explicit RecurringTime(clock::duration daytime, Weekdays days, clock::duration variation = std::chrono::seconds(0)); | 195 | explicit RecurringTime(clock::duration daytime, Weekdays days, clock::duration variation = std::chrono::seconds(0)); |
| 103 | 196 | ||
| 197 | + //! \brief Get time of day | ||
| 104 | clock::duration getDaytime() const; | 198 | clock::duration getDaytime() const; |
| 199 | + //! \brief Get random variation | ||
| 200 | + //! | ||
| 201 | + //! The time can vary up to this amount in both directions. | ||
| 105 | clock::duration getRandomVariation() const; | 202 | clock::duration getRandomVariation() const; |
| 203 | + //! \brief Get days on which the repetition will happen | ||
| 106 | Weekdays getWeekdays() const; | 204 | Weekdays getWeekdays() const; |
| 107 | 205 | ||
| 206 | + //! \brief Get formatted string as expected by Hue API | ||
| 207 | + //! \returns with no variation: | ||
| 208 | + //! <strong>W</strong><code>bbb</code><strong>/T</strong><code>hh:mm:ss</code> | ||
| 209 | + //! \returns with variation: | ||
| 210 | + //! <strong>W</strong><code>bbb</code><strong>/T</strong><code>hh:mm:ss</code><strong>A</strong><code>hh:mm:ss</code>, | ||
| 211 | + //! where daytime is first and variation is second. | ||
| 108 | std::string toString() const; | 212 | std::string toString() const; |
| 109 | 213 | ||
| 110 | private: | 214 | private: |
| @@ -113,17 +217,34 @@ private: | @@ -113,17 +217,34 @@ private: | ||
| 113 | Weekdays days; | 217 | Weekdays days; |
| 114 | }; | 218 | }; |
| 115 | 219 | ||
| 220 | +//! \brief Time interval repeated daily to weekly. | ||
| 221 | +//! | ||
| 222 | +//! Can be used to represent an interval of time on one or multiple days per week. | ||
| 223 | +//! The maximum interval length is 23 hours. | ||
| 116 | class TimeInterval | 224 | class TimeInterval |
| 117 | { | 225 | { |
| 118 | using clock = std::chrono::system_clock; | 226 | using clock = std::chrono::system_clock; |
| 119 | 227 | ||
| 120 | public: | 228 | public: |
| 229 | + //! \brief Create time interval | ||
| 230 | + //! \param start Start time, duration from the start of the day | ||
| 231 | + //! \param end End time, duration from the start of the day | ||
| 232 | + //! \param days Active days, optional. Defaults to daily repetition. | ||
| 121 | TimeInterval(clock::duration start, clock::duration end, Weekdays days = Weekdays::all()); | 233 | TimeInterval(clock::duration start, clock::duration end, Weekdays days = Weekdays::all()); |
| 122 | 234 | ||
| 235 | + //! \brief Get start time of the interval | ||
| 123 | clock::duration getStartTime() const; | 236 | clock::duration getStartTime() const; |
| 237 | + //! \brief Get end time of the interval | ||
| 124 | clock::duration getEndTime() const; | 238 | clock::duration getEndTime() const; |
| 239 | + //! \brief Get active days | ||
| 125 | Weekdays getWeekdays() const; | 240 | Weekdays getWeekdays() const; |
| 126 | 241 | ||
| 242 | + //! \brief Get formatted string as expected by Hue API | ||
| 243 | + //! \returns with daily repetition: | ||
| 244 | + //! <strong>T</strong><code>hh:mm:ss</code><strong>/T</strong><code>hh:mm:ss</code>, | ||
| 245 | + //! with start time first and end time second. | ||
| 246 | + //! \returns with repetition that is not daily: | ||
| 247 | + //! <strong>W</strong><code>bbb</code><strong>/T</strong><code>hh:mm:ss</code><strong>/T</strong><code>hh:mm:ss</code> | ||
| 127 | std::string toString() const; | 248 | std::string toString() const; |
| 128 | 249 | ||
| 129 | private: | 250 | private: |
| @@ -132,19 +253,53 @@ private: | @@ -132,19 +253,53 @@ private: | ||
| 132 | Weekdays days; | 253 | Weekdays days; |
| 133 | }; | 254 | }; |
| 134 | 255 | ||
| 256 | +//! \brief Timer that is started and triggers after specified delay | ||
| 257 | +//! | ||
| 258 | +//! The timer can have a random variation in the expiry time. | ||
| 259 | +//! It can be one-off, repeated a set number of times or repeated indefinitely. | ||
| 135 | class Timer | 260 | class Timer |
| 136 | { | 261 | { |
| 137 | using clock = std::chrono::system_clock; | 262 | using clock = std::chrono::system_clock; |
| 138 | 263 | ||
| 139 | public: | 264 | public: |
| 265 | + // \brief Used to represent infinite repetitions | ||
| 266 | + static constexpr int infiniteExecutions = 0; | ||
| 267 | + | ||
| 268 | + //! \brief Create one-off timer | ||
| 269 | + //! \param duration Expiry time of the timer, max 24 hours. | ||
| 270 | + //! \param variation Random variation of expiry time, optional. | ||
| 140 | Timer(clock::duration duration, clock::duration variation = std::chrono::seconds(0)); | 271 | Timer(clock::duration duration, clock::duration variation = std::chrono::seconds(0)); |
| 272 | + //! \brief Create a repeated timer. | ||
| 273 | + //! \param duration Expiry time of the timer, max 24 hours. | ||
| 274 | + //! \param numExecutions Number of executions, 1 or higher, or \ref infiniteExecutions to always repeat. | ||
| 275 | + //! \param variation Random variation of expiry time, optional. | ||
| 141 | Timer(clock::duration duration, int numExecutions, clock::duration variation = std::chrono::seconds(0)); | 276 | Timer(clock::duration duration, int numExecutions, clock::duration variation = std::chrono::seconds(0)); |
| 142 | 277 | ||
| 278 | + //! \brief Returns true when the timer is executed more than once | ||
| 143 | bool isRecurring() const; | 279 | bool isRecurring() const; |
| 280 | + | ||
| 281 | + //! \brief Get number of executions | ||
| 282 | + //! \returns Number of executions, or \ref infiniteExecutions | ||
| 144 | int getNumberOfExecutions() const; | 283 | int getNumberOfExecutions() const; |
| 284 | + //! \brief Get expiry time | ||
| 145 | clock::duration getExpiryTime() const; | 285 | clock::duration getExpiryTime() const; |
| 286 | + //! \brief Get random variation of expiry time | ||
| 287 | + //! | ||
| 288 | + //! The expiry time can vary up to this value in both directions. | ||
| 146 | clock::duration getRandomVariation() const; | 289 | clock::duration getRandomVariation() const; |
| 147 | 290 | ||
| 291 | + //! \brief Get formatted string as expected by Hue API | ||
| 292 | + //! \returns one-off timer: <strong>PT</strong><code>hh:mm:ss</code> | ||
| 293 | + //! \returns one-off timer with variation: | ||
| 294 | + //! <strong>PT</strong><code>hh:mm:ss</code><strong>A</strong><code>hh:mm:ss</code>, | ||
| 295 | + //! with expiry time first and variation second. | ||
| 296 | + //! \returns recurring timer: <strong>R/PT</strong><code>hh:mm:ss</code> | ||
| 297 | + //! \returns recurring timer with n repetitions: | ||
| 298 | + //! <strong>R</strong><code>nn</code><strong>/PT</strong><code>hh:mm:ss</code> | ||
| 299 | + //! \returns recurring timer with random variation: | ||
| 300 | + //! <strong>R</strong><code>nn</code><strong>/PT</strong><code>hh:mm:ss</code><strong>A</strong><code>hh:mm:ss</code> | ||
| 301 | + //! \returns infinite recurring timer with random variation: | ||
| 302 | + //! <strong>R</strong><strong>/PT</strong><code>hh:mm:ss</code><strong>A</strong><code>hh:mm:ss</code> | ||
| 148 | std::string toString() const; | 303 | std::string toString() const; |
| 149 | 304 | ||
| 150 | private: | 305 | private: |
| @@ -153,41 +308,75 @@ private: | @@ -153,41 +308,75 @@ private: | ||
| 153 | int numExecutions; | 308 | int numExecutions; |
| 154 | }; | 309 | }; |
| 155 | 310 | ||
| 311 | +//! \brief Holds different time representations | ||
| 312 | +//! | ||
| 313 | +//! Holds either AbsoluteTime, RecurringTime, TimeInterval, Timer or an undefined state. | ||
| 314 | +//! TimePattern is used to specify the occurrance of Schedule%s. | ||
| 156 | class TimePattern | 315 | class TimePattern |
| 157 | { | 316 | { |
| 158 | public: | 317 | public: |
| 318 | + //! \brief Currently active type | ||
| 159 | enum class Type | 319 | enum class Type |
| 160 | { | 320 | { |
| 161 | - undefined, | ||
| 162 | - absolute, | ||
| 163 | - recurring, | ||
| 164 | - interval, | ||
| 165 | - timer | 321 | + undefined, //!< \brief No active type |
| 322 | + absolute, //!< \brief Active type is AbsoluteTime | ||
| 323 | + recurring, //!< \brief Active type is RecurringTime | ||
| 324 | + interval, //!< \brief Active type is TimeInterval | ||
| 325 | + timer //!< \brief Active type is Timer | ||
| 166 | }; | 326 | }; |
| 167 | 327 | ||
| 328 | + //! \brief Create empty TimePattern | ||
| 168 | TimePattern(); | 329 | TimePattern(); |
| 330 | + //! \brief Destructor for union. | ||
| 169 | ~TimePattern(); | 331 | ~TimePattern(); |
| 332 | + //! \brief Create TimePattern from AbsoluteTime | ||
| 170 | explicit TimePattern(const AbsoluteTime& absolute); | 333 | explicit TimePattern(const AbsoluteTime& absolute); |
| 334 | + //! \brief Create TimePattern from RecurringTime | ||
| 171 | explicit TimePattern(const RecurringTime& recurring); | 335 | explicit TimePattern(const RecurringTime& recurring); |
| 336 | + //! \brief Create TimePattern from TimeInterval | ||
| 172 | explicit TimePattern(const TimeInterval& interval); | 337 | explicit TimePattern(const TimeInterval& interval); |
| 338 | + //! \brief Create TimePattern from Timer | ||
| 173 | explicit TimePattern(const Timer& timer); | 339 | explicit TimePattern(const Timer& timer); |
| 174 | 340 | ||
| 341 | + //! \brief Copy constructor for union | ||
| 175 | TimePattern(const TimePattern& other); | 342 | TimePattern(const TimePattern& other); |
| 176 | 343 | ||
| 344 | + //! \brief Copy assignment for union | ||
| 177 | TimePattern& operator=(const TimePattern& other); | 345 | TimePattern& operator=(const TimePattern& other); |
| 178 | 346 | ||
| 347 | + //! \brief Get currently active type | ||
| 348 | + //! \note Only the currently active type may be accessed, | ||
| 349 | + //! anything else is undefined behavior. | ||
| 179 | Type getType() const; | 350 | Type getType() const; |
| 180 | 351 | ||
| 352 | + //! \brief Get contained absolute time | ||
| 353 | + //! \pre getType() == Type::absolute | ||
| 181 | AbsoluteTime asAbsolute() const; | 354 | AbsoluteTime asAbsolute() const; |
| 182 | 355 | ||
| 356 | + //! \brief Get contained recurring time | ||
| 357 | + //! \pre getType() == Type::recurring | ||
| 183 | RecurringTime asRecurring() const; | 358 | RecurringTime asRecurring() const; |
| 184 | 359 | ||
| 360 | + //! \brief Get contained time interval | ||
| 361 | + //! \pre getType() == Type::interval | ||
| 185 | TimeInterval asInterval() const; | 362 | TimeInterval asInterval() const; |
| 186 | 363 | ||
| 364 | + //! \brief Get contained timer | ||
| 365 | + //! \pre getType() == Type::timer | ||
| 187 | Timer asTimer() const; | 366 | Timer asTimer() const; |
| 188 | 367 | ||
| 368 | + //! \brief Get formatted string of the contained value as expected by Hue API | ||
| 369 | + //! \returns Empty string when type is undefined, otherwise toString() of the active type. | ||
| 370 | + //! \see AbsoluteTime::toString, RecurringTime::toString, TimeInterval::toString, Timer::toString | ||
| 189 | std::string toString() const; | 371 | std::string toString() const; |
| 190 | 372 | ||
| 373 | + //! \brief Parses TimePattern from formatted string as returned by Hue API | ||
| 374 | + //! \param s Empty string, "none", or in one of the formats the contained types | ||
| 375 | + //! return in their toString() method. | ||
| 376 | + //! \returns TimePattern with the matching type that is given in \c s | ||
| 377 | + //! \see AbsoluteTime::toString, RecurringTime::toString, TimeInterval::toString, Timer::toString | ||
| 378 | + //! \throws HueException when the format does not match or a parsing error occurs | ||
| 379 | + //! \throws std::invalid_argument when an integer conversion fails | ||
| 191 | static TimePattern parse(const std::string& s); | 380 | static TimePattern parse(const std::string& s); |
| 192 | 381 | ||
| 193 | private: | 382 | private: |
include/hueplusplus/Utils.h
src/TimePattern.cpp
| @@ -28,14 +28,19 @@ namespace hueplusplus | @@ -28,14 +28,19 @@ namespace hueplusplus | ||
| 28 | { | 28 | { |
| 29 | namespace time | 29 | namespace time |
| 30 | { | 30 | { |
| 31 | - | ||
| 32 | -using clock = std::chrono::system_clock; | ||
| 33 | -std::string timepointToTimestamp(clock::time_point time) | 31 | +using std::chrono::system_clock; |
| 32 | +// Full name needed for doxygen | ||
| 33 | +std::string timepointToTimestamp(std::chrono::system_clock::time_point time) | ||
| 34 | { | 34 | { |
| 35 | using namespace std::chrono; | 35 | using namespace std::chrono; |
| 36 | - std::time_t ctime = clock::to_time_t(time); | 36 | + std::time_t ctime = system_clock::to_time_t(time); |
| 37 | 37 | ||
| 38 | - std::tm localtime = *std::localtime(&ctime); | 38 | + std::tm* pLocaltime = std::localtime(&ctime); |
| 39 | + if (pLocaltime == nullptr) | ||
| 40 | + { | ||
| 41 | + throw HueException(CURRENT_FILE_INFO, "localtime failed"); | ||
| 42 | + } | ||
| 43 | + std::tm localtime = *pLocaltime; | ||
| 39 | char buf[32]; | 44 | char buf[32]; |
| 40 | 45 | ||
| 41 | std::size_t result = std::strftime(buf, sizeof(buf), "%FT%T", &localtime); | 46 | std::size_t result = std::strftime(buf, sizeof(buf), "%FT%T", &localtime); |
| @@ -46,7 +51,7 @@ std::string timepointToTimestamp(clock::time_point time) | @@ -46,7 +51,7 @@ std::string timepointToTimestamp(clock::time_point time) | ||
| 46 | return std::string(buf); | 51 | return std::string(buf); |
| 47 | } | 52 | } |
| 48 | 53 | ||
| 49 | -clock::time_point parseTimestamp(const std::string& timestamp) | 54 | +system_clock::time_point parseTimestamp(const std::string& timestamp) |
| 50 | { | 55 | { |
| 51 | std::tm tm {}; | 56 | std::tm tm {}; |
| 52 | tm.tm_year = std::stoi(timestamp.substr(0, 4)) - 1900; | 57 | tm.tm_year = std::stoi(timestamp.substr(0, 4)) - 1900; |
| @@ -58,10 +63,15 @@ clock::time_point parseTimestamp(const std::string& timestamp) | @@ -58,10 +63,15 @@ clock::time_point parseTimestamp(const std::string& timestamp) | ||
| 58 | // Auto detect daylight savings time | 63 | // Auto detect daylight savings time |
| 59 | tm.tm_isdst = -1; | 64 | tm.tm_isdst = -1; |
| 60 | std::time_t ctime = std::mktime(&tm); | 65 | std::time_t ctime = std::mktime(&tm); |
| 61 | - return clock::from_time_t(ctime); | 66 | + if (ctime == -1) |
| 67 | + { | ||
| 68 | + throw HueException(CURRENT_FILE_INFO, "mktime failed"); | ||
| 69 | + } | ||
| 70 | + return system_clock::from_time_t(ctime); | ||
| 62 | } | 71 | } |
| 63 | 72 | ||
| 64 | -std::string durationTo_hh_mm_ss(clock::duration duration) | 73 | +// Full name needed for doxygen |
| 74 | +std::string durationTo_hh_mm_ss(std::chrono::system_clock::duration duration) | ||
| 65 | { | 75 | { |
| 66 | using namespace std::chrono; | 76 | using namespace std::chrono; |
| 67 | if (duration > hours(24)) | 77 | if (duration > hours(24)) |
| @@ -79,7 +89,7 @@ std::string durationTo_hh_mm_ss(clock::duration duration) | @@ -79,7 +89,7 @@ std::string durationTo_hh_mm_ss(clock::duration duration) | ||
| 79 | return std::string(result); | 89 | return std::string(result); |
| 80 | } | 90 | } |
| 81 | 91 | ||
| 82 | -clock::duration parseDuration(const std::string& s) | 92 | +system_clock::duration parseDuration(const std::string& s) |
| 83 | { | 93 | { |
| 84 | using namespace std::chrono; | 94 | using namespace std::chrono; |
| 85 | const hours hour(std::stoi(s.substr(0, 2))); | 95 | const hours hour(std::stoi(s.substr(0, 2))); |
| @@ -91,11 +101,11 @@ clock::duration parseDuration(const std::string& s) | @@ -91,11 +101,11 @@ clock::duration parseDuration(const std::string& s) | ||
| 91 | AbsoluteTime::AbsoluteTime(clock::time_point baseTime, clock::duration variation) : base(baseTime), variation(variation) | 101 | AbsoluteTime::AbsoluteTime(clock::time_point baseTime, clock::duration variation) : base(baseTime), variation(variation) |
| 92 | {} | 102 | {} |
| 93 | 103 | ||
| 94 | -clock::time_point AbsoluteTime::getBaseTime() const | 104 | +system_clock::time_point AbsoluteTime::getBaseTime() const |
| 95 | { | 105 | { |
| 96 | return base; | 106 | return base; |
| 97 | } | 107 | } |
| 98 | -clock::duration AbsoluteTime::getRandomVariation() const | 108 | +system_clock::duration AbsoluteTime::getRandomVariation() const |
| 99 | { | 109 | { |
| 100 | return variation; | 110 | return variation; |
| 101 | } | 111 | } |
| @@ -243,12 +253,12 @@ RecurringTime::RecurringTime(clock::duration daytime, Weekdays days, clock::dura | @@ -243,12 +253,12 @@ RecurringTime::RecurringTime(clock::duration daytime, Weekdays days, clock::dura | ||
| 243 | : time(daytime), days(days), variation(variation) | 253 | : time(daytime), days(days), variation(variation) |
| 244 | {} | 254 | {} |
| 245 | 255 | ||
| 246 | -clock::duration RecurringTime::getDaytime() const | 256 | +system_clock::duration RecurringTime::getDaytime() const |
| 247 | { | 257 | { |
| 248 | return time; | 258 | return time; |
| 249 | } | 259 | } |
| 250 | 260 | ||
| 251 | -clock::duration RecurringTime::getRandomVariation() const | 261 | +system_clock::duration RecurringTime::getRandomVariation() const |
| 252 | { | 262 | { |
| 253 | return variation; | 263 | return variation; |
| 254 | } | 264 | } |
| @@ -276,12 +286,12 @@ TimeInterval::TimeInterval(clock::duration start, clock::duration end, Weekdays | @@ -276,12 +286,12 @@ TimeInterval::TimeInterval(clock::duration start, clock::duration end, Weekdays | ||
| 276 | : start(start), end(end), days(days) | 286 | : start(start), end(end), days(days) |
| 277 | {} | 287 | {} |
| 278 | 288 | ||
| 279 | -clock::duration TimeInterval::getStartTime() const | 289 | +system_clock::duration TimeInterval::getStartTime() const |
| 280 | { | 290 | { |
| 281 | return start; | 291 | return start; |
| 282 | } | 292 | } |
| 283 | 293 | ||
| 284 | -clock::duration TimeInterval::getEndTime() const | 294 | +system_clock::duration TimeInterval::getEndTime() const |
| 285 | { | 295 | { |
| 286 | return end; | 296 | return end; |
| 287 | } | 297 | } |
| @@ -326,12 +336,12 @@ int Timer::getNumberOfExecutions() const | @@ -326,12 +336,12 @@ int Timer::getNumberOfExecutions() const | ||
| 326 | return numExecutions; | 336 | return numExecutions; |
| 327 | } | 337 | } |
| 328 | 338 | ||
| 329 | -clock::duration Timer::getExpiryTime() const | 339 | +system_clock::duration Timer::getExpiryTime() const |
| 330 | { | 340 | { |
| 331 | return expires; | 341 | return expires; |
| 332 | } | 342 | } |
| 333 | 343 | ||
| 334 | -clock::duration Timer::getRandomVariation() const | 344 | +system_clock::duration Timer::getRandomVariation() const |
| 335 | { | 345 | { |
| 336 | return variation; | 346 | return variation; |
| 337 | } | 347 | } |
| @@ -342,7 +352,7 @@ std::string Timer::toString() const | @@ -342,7 +352,7 @@ std::string Timer::toString() const | ||
| 342 | if (numExecutions != 1) | 352 | if (numExecutions != 1) |
| 343 | { | 353 | { |
| 344 | result.push_back('R'); | 354 | result.push_back('R'); |
| 345 | - if (numExecutions != 0) | 355 | + if (numExecutions != infiniteExecutions) |
| 346 | { | 356 | { |
| 347 | std::string s = std::to_string(numExecutions); | 357 | std::string s = std::to_string(numExecutions); |
| 348 | // Pad to two digits | 358 | // Pad to two digits |
| @@ -495,8 +505,8 @@ TimePattern TimePattern::parse(const std::string& s) | @@ -495,8 +505,8 @@ TimePattern TimePattern::parse(const std::string& s) | ||
| 495 | } | 505 | } |
| 496 | std::size_t start = s.find('T') + 1; | 506 | std::size_t start = s.find('T') + 1; |
| 497 | std::size_t randomStart = s.find('A'); | 507 | std::size_t randomStart = s.find('A'); |
| 498 | - clock::duration expires = parseDuration(s.substr(start, randomStart - start)); | ||
| 499 | - clock::duration variance = std::chrono::seconds(0); | 508 | + system_clock::duration expires = parseDuration(s.substr(start, randomStart - start)); |
| 509 | + system_clock::duration variance = std::chrono::seconds(0); | ||
| 500 | if (randomStart != std::string::npos) | 510 | if (randomStart != std::string::npos) |
| 501 | { | 511 | { |
| 502 | variance = parseDuration(s.substr(randomStart + 1)); | 512 | variance = parseDuration(s.substr(randomStart + 1)); |
| @@ -507,8 +517,8 @@ TimePattern TimePattern::parse(const std::string& s) | @@ -507,8 +517,8 @@ TimePattern TimePattern::parse(const std::string& s) | ||
| 507 | { | 517 | { |
| 508 | // Recurring time | 518 | // Recurring time |
| 509 | Weekdays days = Weekdays::parse(s.substr(1, 3)); | 519 | Weekdays days = Weekdays::parse(s.substr(1, 3)); |
| 510 | - clock::duration time = parseDuration(s.substr(6)); | ||
| 511 | - clock::duration variation {0}; | 520 | + system_clock::duration time = parseDuration(s.substr(6)); |
| 521 | + system_clock::duration variation {0}; | ||
| 512 | if (s.size() > 14) | 522 | if (s.size() > 14) |
| 513 | { | 523 | { |
| 514 | variation = parseDuration(s.substr(15)); | 524 | variation = parseDuration(s.substr(15)); |
| @@ -526,8 +536,8 @@ TimePattern TimePattern::parse(const std::string& s) | @@ -526,8 +536,8 @@ TimePattern TimePattern::parse(const std::string& s) | ||
| 526 | // Time interval | 536 | // Time interval |
| 527 | std::size_t start = s.find('T') + 1; | 537 | std::size_t start = s.find('T') + 1; |
| 528 | std::size_t end = s.find('/', start); | 538 | std::size_t end = s.find('/', start); |
| 529 | - clock::duration startTime = parseDuration(s.substr(start, end - start)); | ||
| 530 | - clock::duration endTime = parseDuration(s.substr(end + 2)); | 539 | + system_clock::duration startTime = parseDuration(s.substr(start, end - start)); |
| 540 | + system_clock::duration endTime = parseDuration(s.substr(end + 2)); | ||
| 531 | return TimePattern(TimeInterval(startTime, endTime, days)); | 541 | return TimePattern(TimeInterval(startTime, endTime, days)); |
| 532 | } | 542 | } |
| 533 | throw HueException(CURRENT_FILE_INFO, "Unable to parse time string: " + s); | 543 | throw HueException(CURRENT_FILE_INFO, "Unable to parse time string: " + s); |
test/test_TimePattern.cpp
| @@ -299,7 +299,7 @@ TEST(Timer, toString) | @@ -299,7 +299,7 @@ TEST(Timer, toString) | ||
| 299 | EXPECT_EQ("PT00:01:20A01:00:00", timer.toString()); | 299 | EXPECT_EQ("PT00:01:20A01:00:00", timer.toString()); |
| 300 | } | 300 | } |
| 301 | { | 301 | { |
| 302 | - const Timer timer(1min + 20s, 0); | 302 | + const Timer timer(1min + 20s, Timer::infiniteExecutions); |
| 303 | EXPECT_EQ("R/PT00:01:20", timer.toString()); | 303 | EXPECT_EQ("R/PT00:01:20", timer.toString()); |
| 304 | } | 304 | } |
| 305 | { | 305 | { |
| @@ -315,7 +315,7 @@ TEST(Timer, toString) | @@ -315,7 +315,7 @@ TEST(Timer, toString) | ||
| 315 | EXPECT_EQ("R05/PT00:01:20A01:00:00", timer.toString()); | 315 | EXPECT_EQ("R05/PT00:01:20A01:00:00", timer.toString()); |
| 316 | } | 316 | } |
| 317 | { | 317 | { |
| 318 | - const Timer timer(1min + 20s, 0, 1h); | 318 | + const Timer timer(1min + 20s, Timer::infiniteExecutions, 1h); |
| 319 | EXPECT_EQ("R/PT00:01:20A01:00:00", timer.toString()); | 319 | EXPECT_EQ("R/PT00:01:20A01:00:00", timer.toString()); |
| 320 | } | 320 | } |
| 321 | } | 321 | } |
| @@ -449,7 +449,7 @@ TEST(TimePattern, Timer) | @@ -449,7 +449,7 @@ TEST(TimePattern, Timer) | ||
| 449 | EXPECT_EQ(expected.getNumberOfExecutions(), pattern.asTimer().getNumberOfExecutions()); | 449 | EXPECT_EQ(expected.getNumberOfExecutions(), pattern.asTimer().getNumberOfExecutions()); |
| 450 | } | 450 | } |
| 451 | { | 451 | { |
| 452 | - const Timer expected(1h + 30min + 20s, 0); | 452 | + const Timer expected(1h + 30min + 20s, Timer::infiniteExecutions); |
| 453 | const TimePattern pattern = TimePattern::parse("R/PT01:30:20"); | 453 | const TimePattern pattern = TimePattern::parse("R/PT01:30:20"); |
| 454 | ASSERT_EQ(TimePattern::Type::timer, pattern.getType()); | 454 | ASSERT_EQ(TimePattern::Type::timer, pattern.getType()); |
| 455 | EXPECT_EQ(expected.getExpiryTime(), pattern.asTimer().getExpiryTime()); | 455 | EXPECT_EQ(expected.getExpiryTime(), pattern.asTimer().getExpiryTime()); |
| @@ -457,7 +457,7 @@ TEST(TimePattern, Timer) | @@ -457,7 +457,7 @@ TEST(TimePattern, Timer) | ||
| 457 | EXPECT_EQ(expected.getNumberOfExecutions(), pattern.asTimer().getNumberOfExecutions()); | 457 | EXPECT_EQ(expected.getNumberOfExecutions(), pattern.asTimer().getNumberOfExecutions()); |
| 458 | } | 458 | } |
| 459 | { | 459 | { |
| 460 | - const Timer expected(1h + 30min + 20s, 0, 20s); | 460 | + const Timer expected(1h + 30min + 20s, Timer::infiniteExecutions, 20s); |
| 461 | const TimePattern pattern = TimePattern::parse("R/PT01:30:20A00:00:20"); | 461 | const TimePattern pattern = TimePattern::parse("R/PT01:30:20A00:00:20"); |
| 462 | ASSERT_EQ(TimePattern::Type::timer, pattern.getType()); | 462 | ASSERT_EQ(TimePattern::Type::timer, pattern.getType()); |
| 463 | EXPECT_EQ(expected.getExpiryTime(), pattern.asTimer().getExpiryTime()); | 463 | EXPECT_EQ(expected.getExpiryTime(), pattern.asTimer().getExpiryTime()); |