1 // This may look like C code, but it's really -*- C++ -*- 2 /* 3 * Copyright (C) 2009 Emweb bv, Herent, Belgium. 4 * 5 * See the LICENSE file for terms of use. 6 */ 7 #ifndef WTIME_H_ 8 #define WTIME_H_ 9 10 #include <Wt/WDateTime.h> 11 #include <Wt/WString.h> 12 #include <Wt/WStringStream.h> 13 #include <exception> 14 15 namespace Wt { 16 17 /*! \class WTime Wt/WTime.h Wt/WTime.h 18 * \brief A value class that defines a clock time. 19 * 20 * A clock time represents the time of day (usually 0 to 24 hour), up 21 * to millisecond precision. 22 * 23 * As of version %3.3.1, the time class itself will no longer limit times 24 * to the 24-hour range, but will allow any time (duration), including negative 25 * values. 26 * 27 * \sa WDate, WDateTime 28 */ 29 class WT_API WTime 30 { 31 public: 32 /*! \brief Construct a <i>Null</i> time. 33 * 34 * A time for which isNull() returns true. A <i>Null</i> time is also 35 * invalid. 36 * 37 * \sa isValid(), isNull() 38 */ 39 WTime(); 40 41 /*! \brief Construct a time given hour, minutes, seconds, and milliseconds. 42 * 43 * \p m and \p s have range 0-59, and \p ms has range 0-999. A duration can 44 * be positive or negative depending on the sign of \p h. 45 * 46 * When the time is invalid, isValid() is set to \c false. 47 */ 48 WTime(int h, int m, int s = 0, int ms = 0); 49 50 /*! \brief Sets the time. 51 * 52 * \p m and \p s have range 0-59, and \p ms has range 0-999. 53 * 54 * When the time is invalid, isValid() is set to \c false. 55 */ 56 bool setHMS(int h, int m, int s, int ms = 0); 57 58 /*! \brief Adds seconds. 59 * 60 * Returns a time that is \p s seconds later than this time. Negative 61 * values for \p s will result in a time that is as many seconds 62 * earlier. 63 */ 64 WTime addSecs(int s) const; 65 66 /*! \brief Adds milliseconds. 67 * 68 * Returns a time that is \p ms milliseconds later than this 69 * time. Negative values for \p ms will result in a time that 70 * is as many milliseconds earlier. 71 */ 72 WTime addMSecs(int ms) const; 73 74 /*! \brief Returns if this time is <i>Null</i>. 75 * 76 * A null time is also invalid. 77 * 78 * \sa isValid(), WTime() 79 */ isNull()80 bool isNull() const { return null_; } 81 82 /*! \brief Returns if this time is valid. 83 */ isValid()84 bool isValid() const { return valid_; } 85 86 /*! \brief Returns the hour. 87 */ 88 int hour() const; 89 90 /*! \brief Returns the minutes (0-59). 91 */ 92 int minute() const; 93 94 /*! \brief Returns the seconds (0-59). 95 */ 96 int second() const; 97 98 /*! \brief Returns the milliseconds (0-999) 99 */ 100 int msec() const; 101 102 /*! \brief Returns the difference between two time values (in seconds). 103 * 104 * The result is negative if t is earlier than this. 105 */ 106 long secsTo(const WTime& t) const; 107 108 /*! \brief Returns the difference between two time values (in milliseconds). 109 * 110 * The result is negative if t is earlier than this. 111 */ 112 long msecsTo(const WTime& t) const; 113 114 /*! \brief Compares two time values. 115 */ 116 bool operator< (const WTime& other) const; 117 118 /*! \brief Compares two time values. 119 */ 120 bool operator<= (const WTime& other) const; 121 122 /*! \brief Compares two time values. 123 */ 124 bool operator> (const WTime& other) const; 125 126 /*! \brief Compares two time values. 127 */ 128 bool operator>= (const WTime& other) const; 129 130 /*! \brief Compares two time values. 131 */ 132 bool operator== (const WTime& other) const; 133 134 /*! \brief Compares two time values. 135 */ 136 bool operator!= (const WTime& other) const; 137 138 static WT_USTRING defaultFormat(); 139 140 /*! \brief Formats this time to a string using a default format. 141 * 142 * The default format is "hh:mm:ss". 143 */ 144 WT_USTRING toString() const; 145 146 /*! \brief Formats this time to a string using a specified format. 147 * 148 * The \p format is a string in which the following contents has 149 * a special meaning. 150 * 151 * <table> 152 * <tr><td><b>Code</b></td><td><b>Meaning</b></td> 153 * <td><b>Example (for 14:06:23.045)</b></td></tr> 154 * <tr><td>h</td><td>The hour without leading zero (0-23 or 1-12 for AM/PM display)</td> 155 <td>14 or 2</td></tr> 156 * <tr><td>hh</td><td>The hour with leading zero (00-23 or 01-12 for AM/PM display)</td> 157 <td>14 or 02</td></tr> 158 * <tr><td>H</td><td>The hour without leading zero (0-23)</td> 159 <td>14</td></tr> 160 * <tr><td>HH</td><td>The hour with leading zero (00-23)</td> 161 <td>14</td></tr> 162 * <tr><td>+ followed by (h/hh/H/HH)</td><td>The sign of the hour (+/-)</td> 163 <td>+</td></tr> 164 * <tr><td>m</td><td>The minutes without leading zero (0-59)</td> 165 <td>6</td></tr> 166 * <tr><td>mm</td><td>The minutes with leading zero (00-59)</td> 167 <td>06</td></tr> 168 * <tr><td>s</td><td>The seconds without leading zero (0-59)</td> 169 <td>23</td></tr> 170 * <tr><td>ss</td><td>The seconds with leading zero (00-59)</td> 171 <td>23</td></tr> 172 * <tr><td>z</td><td>The milliseconds without leading zero (0-999)</td> 173 <td>45</td></tr> 174 * <tr><td>zzz</td><td>The millisecons with leading zero (000-999)</td> 175 <td>045</td></tr> 176 * <tr><td>AP or A</td><td>use AM/PM display: affects h or hh display and is replaced itself by AM/PM</td> 177 <td>PM</td></tr> 178 * <tr><td>ap or a</td><td>use am/pm display: affects h or hh display and is replaced itself by am/pm</td> 179 <td>pm</td></tr> 180 * <tr><td>Z</td><td>the timezone in RFC 822 format (e.g. -0800)</td> 181 <td>+0000</td></tr> 182 * </table> 183 * 184 * Any other text is kept literally. String content between single 185 * quotes (') are not interpreted as special codes. LabelOption::Inside a string, a literal 186 * quote may be specifed using a double quote (''). 187 * 188 * Examples of format and result: 189 * <table> 190 * <tr><td><b>Format</b></td><td><b>Result (for 22:53:13.078)</b></td></tr> 191 * <tr><td>hh:mm:ss.zzz</td><td>22:53:13.078</td></tr> 192 * <tr><td>hh:mm:ss AP</td><td>10:53:13 PM</td></tr> 193 * </table> 194 * 195 * \sa fromString(const WString& value, const WString& format) 196 */ 197 WT_USTRING toString(const WT_USTRING& format) const; 198 199 /*! \brief Parses a string to a time using a default format. 200 * 201 * The default format is "hh:mm:ss". 202 * For example, a time specified as: 203 * \code 204 * "22:55:15" 205 * \endcode 206 * will be parsed as a time that equals a time constructed as: 207 * \code 208 * WTime d(22,55,15); 209 * \endcode 210 * 211 * When the time could not be parsed or is not valid, an invalid 212 * time is returned (for which isValid() returns false). 213 * 214 * \sa fromString(const WString& s, const WString& format), isValid() 215 */ 216 static WTime fromString(const WT_USTRING& s); 217 218 /*! \brief Parses a string to a time using a specified format. 219 * 220 * The \p format follows the same syntax as used by 221 * \link toString(const WString& format) const toString(const WString& format)\endlink. 222 * 223 * When the time could not be parsed or is not valid, an invalid 224 * time is returned (for which isValid() returns false). 225 * 226 * \sa toString(const WString&) const 227 */ 228 static WTime fromString(const WT_USTRING& s, const WT_USTRING& format); 229 230 /*! \brief Reports the current client date. 231 * 232 * This method uses browser information to retrieve the time that is 233 * configured in the client. 234 * 235 * \sa WLocalDateTime::currentDate() 236 */ 237 static WTime currentTime(); 238 239 /*! \brief Reports the current server time. 240 * 241 * This method returns the local time on the server. 242 * 243 * \sa WDateTime::currentDateTime(), WLocalDateTime::currentServerDateTime() 244 */ 245 static WTime currentServerTime(); 246 247 struct RegExpInfo { 248 std::string regexp; 249 std::string hourGetJS; 250 std::string minuteGetJS; 251 std::string secGetJS; 252 std::string msecGetJS; 253 }; 254 255 static RegExpInfo formatToRegExp(const WT_USTRING& format); 256 257 #ifndef WT_TARGET_JAVA 258 std::chrono::duration<int, std::milli> toTimeDuration() const; 259 static WTime fromTimeDuration(const std::chrono::duration<int, std::milli>& duration); 260 #else 261 std::chrono::milliseconds toTimeDuration() const; 262 static WTime fromTimeDuration(const std::chrono::milliseconds& duration); 263 #endif 264 265 private: 266 bool valid_, null_; 267 long time_; 268 269 WTime (long time); 270 271 struct ParseState { 272 int h, m, s, z, a; 273 int hour, minute, sec, msec; 274 bool pm, parseAMPM, haveAMPM; 275 276 ParseState(); 277 }; 278 279 static bool parseLast(const std::string& v, unsigned& vi, 280 ParseState& parse, const WString& format); 281 282 static WDateTime::CharState handleSpecial(char c, const std::string& v, 283 unsigned& vi, ParseState& parse, 284 const WString& format); 285 286 bool writeSpecial(const std::string& f, unsigned& i, WStringStream& result, 287 bool useAMPM, int zoneOffset) const; 288 289 int pmhour() const; 290 291 static RegExpInfo formatHourToRegExp(RegExpInfo &result, const std::string& format, unsigned& i, int& currentGroup); 292 static RegExpInfo formatMinuteToRegExp(RegExpInfo &result, const std::string& format, unsigned& i, int& currentGroup); 293 static RegExpInfo formatSecondToRegExp(RegExpInfo &result, const std::string& format, unsigned& i, int& currentGroup); 294 static RegExpInfo formatMSecondToRegExp(RegExpInfo &result, const std::string& format, unsigned& i, int& currentGroup); 295 static RegExpInfo formatAPToRegExp(RegExpInfo &result, const std::string& format, unsigned& i); 296 static RegExpInfo processChar(RegExpInfo &result, const std::string& format, unsigned& i); 297 static bool usesAmPm(const WString& format); 298 299 friend class WDateTime; 300 friend class WTimePicker; 301 }; 302 303 } 304 305 #endif // WTIME_H_ 306