Coverage Report

Created: 2026-06-10 06:21

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