MythTV master
mythdate.cpp
Go to the documentation of this file.
1#include <array>
2
3#include <QtGlobal>
4#include <QCoreApplication>
5#include <QRegularExpression>
6#include <QTimeZone>
7
8#include "mythcorecontext.h"
9#include "mythdate.h"
10#include "stringutil.h"
11
12namespace MythDate
13{
14
15QDateTime current(bool stripped)
16{
17 QDateTime rettime = QDateTime::currentDateTimeUtc();
18 if (stripped)
19 rettime = rettime.addMSecs(-rettime.time().msec());
20 return rettime;
21}
22
23QString current_iso_string(bool stripped)
24{
25 return MythDate::current(stripped).toString(Qt::ISODate);
26}
27
28QDateTime as_utc(const QDateTime &old_dt)
29{
30 QDateTime dt(old_dt);
31#if QT_VERSION < QT_VERSION_CHECK(6,5,0)
32 dt.setTimeSpec(Qt::UTC);
33#else
34 dt.setTimeZone(QTimeZone(QTimeZone::UTC));
35#endif
36 return dt;
37}
38
39QDateTime fromString(const QString &dtstr)
40{
41 QDateTime dt;
42 if (dtstr.isEmpty())
43 return as_utc(dt);
44
45 if (!dtstr.contains("-") && dtstr.length() == 14)
46 {
47 // must be in yyyyMMddhhmmss format
48 dt = QDateTime::fromString(dtstr, "yyyyMMddhhmmss");
49 }
50 else
51 {
53 }
54
55 return as_utc(dt);
56}
57
58MBASE_PUBLIC QDateTime fromString(const QString &str, const QString &format)
59{
60 QDateTime dt = QDateTime::fromString(str, format);
61#if QT_VERSION < QT_VERSION_CHECK(6,5,0)
62 dt.setTimeSpec(Qt::UTC);
63#else
64 dt.setTimeZone(QTimeZone(QTimeZone::UTC));
65#endif
66 return dt;
67}
68
81MBASE_PUBLIC QDateTime fromSecsSinceEpoch(int64_t seconds)
82{
83 QDateTime dt = QDateTime::fromSecsSinceEpoch(seconds);
84 return dt.toUTC();
85}
86
93QString toString(const QDateTime &raw_dt, uint format)
94{
95 QString result;
96
97 if (!raw_dt.isValid())
98 return result;
99
100 // if no format is set default to UTC for ISO/file/DB dates.
101 if (!((format & kOverrideUTC) || (format & kOverrideLocal)))
102 {
103 format |= ((ISODate|kFilename|kDatabase) & format) ?
105 }
106
107 QDateTime datetime =
108 (format & kOverrideUTC) ? raw_dt.toUTC() : raw_dt.toLocalTime();
109
110 if (format & kDatabase)
111 return datetime.toString("yyyy-MM-dd hh:mm:ss");
112
113 if (format & MythDate::ISODate)
114 return datetime.toString(Qt::ISODate);
115
116 if (format & MythDate::kRFC822) // RFC 822 - RFC 7231 Sect 7.1.1.1 - HTTP Date
117 return datetime.toUTC().toString("ddd, dd MMM yyyy hh:mm:ss").append(" GMT");
118
119 if (format & kFilename)
120 return datetime.toString("yyyyMMddhhmmss");
121
122 if (format & kScreenShotFilename)
123 return datetime.toString("yyyy-MM-ddThh-mm-ss.zzz");
124
125 if (format & kDateEither)
126 result += toString(datetime.date(), format);
127
128 if (format & kTime)
129 {
130 if (!result.isEmpty())
131 result.append(", ");
132
133 QString timeformat = gCoreContext->GetSetting("TimeFormat", "h:mm AP");
134 result += datetime.time().toString(timeformat);
135 }
136
137 return result;
138}
139
145QString toString(const QDate date, uint format)
146{
147 QString result;
148
149 if (!date.isValid())
150 return result;
151
152 if (format & kDateEither)
153 {
154 QString stringformat;
155 if (format & kDateShort)
156 stringformat = gCoreContext->GetSetting("ShortDateFormat", "ddd d");
157 else
158 stringformat = gCoreContext->GetSetting("DateFormat", "ddd d MMMM");
159
160 if (format & kAddYear)
161 {
162 if (!stringformat.contains("yy")) // Matches both 2 or 4 digit year
163 stringformat.append(" yyyy");
164 }
165
166 if (format & kAutoYear)
167 {
168 if (!stringformat.contains("yy") // Matches both 2 or 4 digit year
169 && date.year() != QDateTime::currentDateTime().date().year())
170 stringformat.append(" yyyy");
171 }
172
173 if (format & ~kDateShort)
174 {
175 QDate now = current().toLocalTime().date();
176 if ((format & kSimplify) && (now == date))
177 result = QCoreApplication::translate("(Common)", "Today");
178 else if (((format & kSimplify) != 0U) && (now.addDays(-1) == date))
179 result = QCoreApplication::translate("(Common)", "Yesterday");
180 else if (((format & kSimplify) != 0U) && (now.addDays(1) == date))
181 result = QCoreApplication::translate("(Common)", "Tomorrow");
182 }
183
184 if (result.isEmpty())
185 result = gCoreContext->GetQLocale().toString(date, stringformat);
186 }
187
188 return result;
189}
190
195std::chrono::seconds toSeconds(QTime time)
196{
197 if (!time.isValid())
198 return 0s;
199
200 std::chrono::seconds nSecs = std::chrono::hours(time.hour());
201 nSecs += std::chrono::minutes(time.minute());
202 nSecs += std::chrono::seconds(time.second());
203
204 return nSecs;
205}
206
207std::chrono::milliseconds currentMSecsSinceEpochAsDuration(void)
208{
209 return std::chrono::milliseconds(QDateTime::currentMSecsSinceEpoch());
210};
211
212std::chrono::seconds secsInPast (const QDateTime& past)
213{
214 return std::chrono::seconds(past.secsTo(MythDate::current()));
215}
216
217std::chrono::seconds secsInFuture (const QDateTime& future)
218{
219 return std::chrono::seconds(MythDate::current().secsTo(future));
220}
221
242QString formatTime(std::chrono::milliseconds msecs, QString fmt)
243{
244 static const QRegularExpression hRe("H+");
245 static const QRegularExpression mRe("m+");
246 static const QRegularExpression sRe("s+");
247 static const QRegularExpression zRe("z+");
248
249 bool negativeTime = msecs < 0ms;
250 msecs = std::chrono::milliseconds(std::abs(msecs.count()));
251
252 QRegularExpressionMatch match = hRe.match(fmt);
253 if (match.hasMatch())
254 {
255 int width = match.capturedLength();
256 QString text = StringUtil::intToPaddedString(msecs / 1h, width);
257 fmt.replace(match.capturedStart(), width, text);
258 msecs = msecs % 1h;
259 }
260
261 match = mRe.match(fmt);
262 if (match.hasMatch())
263 {
264 int width = match.capturedLength();
265 QString text = StringUtil::intToPaddedString(msecs / 1min, width);
266 fmt.replace(match.capturedStart(), width, text);
267 msecs = msecs % 1min;
268 }
269
270 match = sRe.match(fmt);
271 if (match.hasMatch())
272 {
273 int width = match.capturedLength();
274 QString text = StringUtil::intToPaddedString(msecs / 1s, width);
275 fmt.replace(match.capturedStart(), width, text);
276 }
277
278 match = zRe.match(fmt);
279 if (match.hasMatch())
280 {
281 static constexpr std::array<int,4> divisor = {1000, 100, 10, 1};
282#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
283 int width = std::min(3, match.capturedLength());
284#else
285 int width = std::min(static_cast<qsizetype>(3), match.capturedLength());
286#endif
287 int value = (msecs % 1s).count() / divisor[width];
288 QString text = StringUtil::intToPaddedString(value, width);
289 fmt.replace(match.capturedStart(), match.capturedLength(), text);
290 }
291
292 if (negativeTime)
293 fmt.prepend("-");
294
295 return fmt;
296}
297
298}; // namespace MythDate
QLocale GetQLocale(void)
QString GetSetting(const QString &key, const QString &defaultval="")
unsigned int uint
Definition: freesurround.h:24
#define MBASE_PUBLIC
Definition: mythbaseexp.h:15
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
QString current_iso_string(bool stripped)
Returns current Date and Time in UTC as a string.
Definition: mythdate.cpp:23
QString formatTime(std::chrono::milliseconds msecs, QString fmt)
Format a milliseconds time value.
Definition: mythdate.cpp:242
std::chrono::milliseconds currentMSecsSinceEpochAsDuration(void)
Definition: mythdate.cpp:207
QDateTime as_utc(const QDateTime &old_dt)
Returns copy of QDateTime with TimeSpec set to UTC.
Definition: mythdate.cpp:28
std::chrono::seconds secsInPast(const QDateTime &past)
Definition: mythdate.cpp:212
MBASE_PUBLIC QDateTime fromSecsSinceEpoch(int64_t seconds)
This function takes the number of seconds since the start of the epoch and returns a QDateTime with t...
Definition: mythdate.cpp:81
QString toString(const QDateTime &raw_dt, uint format)
Returns formatted string representing the time.
Definition: mythdate.cpp:93
@ kOverrideUTC
Present date/time in UTC.
Definition: mythdate.h:31
@ kScreenShotFilename
"yyyy-MM-ddThh-mm-ss.zzz"
Definition: mythdate.h:29
@ kFilename
Default UTC, "yyyyMMddhhmmss".
Definition: mythdate.h:18
@ kRFC822
HTTP Date format.
Definition: mythdate.h:30
@ kSimplify
Do Today/Yesterday/Tomorrow transform.
Definition: mythdate.h:26
@ ISODate
Default UTC.
Definition: mythdate.h:17
@ kTime
Default local time.
Definition: mythdate.h:22
@ kAddYear
Add year to string if not included.
Definition: mythdate.h:25
@ kOverrideLocal
Present date/time in localtime.
Definition: mythdate.h:32
@ kDateEither
Default local time.
Definition: mythdate.h:21
@ kDateShort
Default local time.
Definition: mythdate.h:20
@ kDatabase
Default UTC, database format.
Definition: mythdate.h:27
@ kAutoYear
Add year only if different from current year.
Definition: mythdate.h:28
std::chrono::seconds secsInFuture(const QDateTime &future)
Definition: mythdate.cpp:217
QDateTime fromString(const QString &dtstr)
Converts kFilename && kISODate formats to QDateTime.
Definition: mythdate.cpp:39
std::chrono::seconds toSeconds(QTime time)
Returns the total number of seconds since midnight of the supplied QTime.
Definition: mythdate.cpp:195
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:15
MBASE_PUBLIC QDateTime fromString(const QString &str, const QString &format)
Converts dy in format to QDateTime.
Definition: mythdate.cpp:58
QString intToPaddedString(int n, int width=2)
Creates a zero padded string representation of an integer.
Definition: stringutil.h:27
string timeformat
Definition: mythburn.py:170