OpenShot Audio Library | OpenShotAudio 0.4.0
juce_Time.cpp
1/*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - Raw Material Software Limited
6
7 JUCE is an open source library subject to commercial or open-source
8 licensing.
9
10 The code included in this file is provided under the terms of the ISC license
11 http://www.isc.org/downloads/software-support-policy/isc-license. Permission
12 To use, copy, modify, and/or distribute this software for any purpose with or
13 without fee is hereby granted provided that the above copyright notice and
14 this permission notice appear in all copies.
15
16 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
18 DISCLAIMED.
19
20 ==============================================================================
21*/
22
23namespace juce
24{
25
26namespace TimeHelpers
27{
28 static std::tm millisToLocal (int64 millis) noexcept
29 {
30 #if JUCE_WINDOWS && JUCE_MINGW
31 auto now = (time_t) (millis / 1000);
32 return *localtime (&now);
33
34 #elif JUCE_WINDOWS
35 std::tm result;
36 millis /= 1000;
37
38 if (_localtime64_s (&result, &millis) != 0)
39 zerostruct (result);
40
41 return result;
42
43 #else
44 std::tm result;
45 auto now = (time_t) (millis / 1000);
46
47 if (localtime_r (&now, &result) == nullptr)
48 zerostruct (result);
49
50 return result;
51 #endif
52 }
53
54 static std::tm millisToUTC (int64 millis) noexcept
55 {
56 #if JUCE_WINDOWS && JUCE_MINGW
57 auto now = (time_t) (millis / 1000);
58 return *gmtime (&now);
59
60 #elif JUCE_WINDOWS
61 std::tm result;
62 millis /= 1000;
63
64 if (_gmtime64_s (&result, &millis) != 0)
65 zerostruct (result);
66
67 return result;
68
69 #else
70 std::tm result;
71 auto now = (time_t) (millis / 1000);
72
73 if (gmtime_r (&now, &result) == nullptr)
74 zerostruct (result);
75
76 return result;
77 #endif
78 }
79
80 static int getUTCOffsetSeconds (const int64 millis) noexcept
81 {
82 auto utc = millisToUTC (millis);
83 utc.tm_isdst = -1; // Treat this UTC time as local to find the offset
84
85 return (int) ((millis / 1000) - (int64) mktime (&utc));
86 }
87
88 static int extendedModulo (const int64 value, const int modulo) noexcept
89 {
90 return (int) (value >= 0 ? (value % modulo)
91 : (value - ((value / modulo) + 1) * modulo));
92 }
93
94 static String formatString (const String& format, const std::tm* const tm)
95 {
96 #if JUCE_ANDROID
97 using StringType = CharPointer_UTF8;
98 #elif JUCE_WINDOWS
99 using StringType = CharPointer_UTF16;
100 #else
101 using StringType = CharPointer_UTF32;
102 #endif
103
104 #ifdef JUCE_MSVC
105 if (tm->tm_year < -1900 || tm->tm_year > 8099)
106 return {}; // Visual Studio's library can only handle 0 -> 9999 AD
107 #endif
108
109 for (size_t bufferSize = 256; ; bufferSize += 256)
110 {
111 HeapBlock<StringType::CharType> buffer (bufferSize);
112
113 auto numChars =
114 #if JUCE_ANDROID
115 strftime (buffer, bufferSize - 1, format.toUTF8(), tm);
116 #elif JUCE_WINDOWS
117 wcsftime (buffer, bufferSize - 1, format.toWideCharPointer(), tm);
118 #else
119 wcsftime (buffer, bufferSize - 1, format.toUTF32(), tm);
120 #endif
121
122 if (numChars > 0 || format.isEmpty())
123 return String (StringType (buffer),
124 StringType (buffer) + (int) numChars);
125 }
126 }
127
128 //==============================================================================
129 static bool isLeapYear (int year) noexcept
130 {
131 return (year % 400 == 0) || ((year % 100 != 0) && (year % 4 == 0));
132 }
133
134 static int daysFromJan1 (int year, int month) noexcept
135 {
136 const short dayOfYear[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334,
137 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 };
138
139 return dayOfYear [(isLeapYear (year) ? 12 : 0) + month];
140 }
141
142 static int64 daysFromYear0 (int year) noexcept
143 {
144 --year;
145 return 365 * year + (year / 400) - (year / 100) + (year / 4);
146 }
147
148 static int64 daysFrom1970 (int year) noexcept
149 {
150 return daysFromYear0 (year) - daysFromYear0 (1970);
151 }
152
153 static int64 daysFrom1970 (int year, int month) noexcept
154 {
155 if (month > 11)
156 {
157 year += month / 12;
158 month %= 12;
159 }
160 else if (month < 0)
161 {
162 auto numYears = (11 - month) / 12;
163 year -= numYears;
164 month += 12 * numYears;
165 }
166
167 return daysFrom1970 (year) + daysFromJan1 (year, month);
168 }
169
170 // There's no posix function that does a UTC version of mktime,
171 // so annoyingly we need to implement this manually..
172 static int64 mktime_utc (const std::tm& t) noexcept
173 {
174 return 24 * 3600 * (daysFrom1970 (t.tm_year + 1900, t.tm_mon) + (t.tm_mday - 1))
175 + 3600 * t.tm_hour
176 + 60 * t.tm_min
177 + t.tm_sec;
178 }
179
180 static Atomic<uint32> lastMSCounterValue { (uint32) 0 };
181
182 static String getUTCOffsetString (int utcOffsetSeconds, bool includeSemiColon)
183 {
184 if (const auto seconds = utcOffsetSeconds)
185 {
186 auto minutes = seconds / 60;
187
188 return String::formatted (includeSemiColon ? "%+03d:%02d"
189 : "%+03d%02d",
190 minutes / 60,
191 abs (minutes) % 60);
192 }
193
194 return "Z";
195 }
196}
197
198//==============================================================================
199Time::Time (int64 ms) noexcept : millisSinceEpoch (ms) {}
200
201Time::Time (int year, int month, int day,
202 int hours, int minutes, int seconds, int milliseconds,
203 bool useLocalTime) noexcept
204{
205 std::tm t;
206 t.tm_year = year - 1900;
207 t.tm_mon = month;
208 t.tm_mday = day;
209 t.tm_hour = hours;
210 t.tm_min = minutes;
211 t.tm_sec = seconds;
212 t.tm_isdst = -1;
213
214 millisSinceEpoch = 1000 * (useLocalTime ? (int64) mktime (&t)
215 : TimeHelpers::mktime_utc (t))
216 + milliseconds;
217}
218
219//==============================================================================
221{
222 #if JUCE_WINDOWS && ! JUCE_MINGW
223 struct _timeb t;
224 _ftime_s (&t);
225 return ((int64) t.time) * 1000 + t.millitm;
226 #else
227 struct timeval tv;
228 gettimeofday (&tv, nullptr);
229 return ((int64) tv.tv_sec) * 1000 + tv.tv_usec / 1000;
230 #endif
231}
232
233Time JUCE_CALLTYPE Time::getCurrentTime() noexcept
234{
235 return Time (currentTimeMillis());
236}
237
238//==============================================================================
239uint32 juce_millisecondsSinceStartup() noexcept;
240
241uint32 Time::getMillisecondCounter() noexcept
242{
243 auto now = juce_millisecondsSinceStartup();
244
245 if (now < TimeHelpers::lastMSCounterValue.get())
246 {
247 // in multi-threaded apps this might be called concurrently, so
248 // make sure that our last counter value only increases and doesn't
249 // go backwards..
250 if (now < TimeHelpers::lastMSCounterValue.get() - (uint32) 1000)
251 TimeHelpers::lastMSCounterValue = now;
252 }
253 else
254 {
255 TimeHelpers::lastMSCounterValue = now;
256 }
257
258 return now;
259}
260
262{
263 auto t = TimeHelpers::lastMSCounterValue.get();
264 return t == 0 ? getMillisecondCounter() : t;
265}
266
267void Time::waitForMillisecondCounter (uint32 targetTime) noexcept
268{
269 for (;;)
270 {
271 auto now = getMillisecondCounter();
272
273 if (now >= targetTime)
274 break;
275
276 auto toWait = (int) (targetTime - now);
277
278 if (toWait > 2)
279 {
280 Thread::sleep (jmin (20, toWait >> 1));
281 }
282 else
283 {
284 // xxx should consider using mutex_pause on the mac as it apparently
285 // makes it seem less like a spinlock and avoids lowering the thread pri.
286 for (int i = 10; --i >= 0;)
288 }
289 }
290}
291
292//==============================================================================
293double Time::highResolutionTicksToSeconds (const int64 ticks) noexcept
294{
295 return (double) ticks / (double) getHighResolutionTicksPerSecond();
296}
297
298int64 Time::secondsToHighResolutionTicks (const double seconds) noexcept
299{
300 return (int64) (seconds * (double) getHighResolutionTicksPerSecond());
301}
302
303//==============================================================================
304String Time::toString (bool includeDate,
305 bool includeTime,
306 bool includeSeconds,
307 bool use24HourClock) const
308{
309 String result;
310
311 if (includeDate)
312 {
313 result << getDayOfMonth() << ' '
314 << getMonthName (true) << ' '
315 << getYear();
316
317 if (includeTime)
318 result << ' ';
319 }
320
321 if (includeTime)
322 {
323 auto mins = getMinutes();
324
325 result << (use24HourClock ? getHours() : getHoursInAmPmFormat())
326 << (mins < 10 ? ":0" : ":") << mins;
327
328 if (includeSeconds)
329 {
330 auto secs = getSeconds();
331 result << (secs < 10 ? ":0" : ":") << secs;
332 }
333
334 if (! use24HourClock)
335 result << (isAfternoon() ? "pm" : "am");
336 }
337
338 return result.trimEnd();
339}
340
341String Time::formatted (const String& format) const
342{
343 std::tm t (TimeHelpers::millisToLocal (millisSinceEpoch));
344 return TimeHelpers::formatString (format, &t);
345}
346
347//==============================================================================
348int Time::getYear() const noexcept { return TimeHelpers::millisToLocal (millisSinceEpoch).tm_year + 1900; }
349int Time::getMonth() const noexcept { return TimeHelpers::millisToLocal (millisSinceEpoch).tm_mon; }
350int Time::getDayOfYear() const noexcept { return TimeHelpers::millisToLocal (millisSinceEpoch).tm_yday; }
351int Time::getDayOfMonth() const noexcept { return TimeHelpers::millisToLocal (millisSinceEpoch).tm_mday; }
352int Time::getDayOfWeek() const noexcept { return TimeHelpers::millisToLocal (millisSinceEpoch).tm_wday; }
353int Time::getHours() const noexcept { return TimeHelpers::millisToLocal (millisSinceEpoch).tm_hour; }
354int Time::getMinutes() const noexcept { return TimeHelpers::millisToLocal (millisSinceEpoch).tm_min; }
355int Time::getSeconds() const noexcept { return TimeHelpers::extendedModulo (millisSinceEpoch / 1000, 60); }
356int Time::getMilliseconds() const noexcept { return TimeHelpers::extendedModulo (millisSinceEpoch, 1000); }
357
358int Time::getHoursInAmPmFormat() const noexcept
359{
360 auto hours = getHours();
361
362 if (hours == 0) return 12;
363 if (hours <= 12) return hours;
364
365 return hours - 12;
366}
367
368bool Time::isAfternoon() const noexcept
369{
370 return getHours() >= 12;
371}
372
373bool Time::isDaylightSavingTime() const noexcept
374{
375 return TimeHelpers::millisToLocal (millisSinceEpoch).tm_isdst != 0;
376}
377
379{
380 String zone[2];
381
382 #if JUCE_WINDOWS && (JUCE_MSVC || JUCE_CLANG)
383 _tzset();
384
385 for (int i = 0; i < 2; ++i)
386 {
387 char name[128] = { 0 };
388 size_t length;
389 _get_tzname (&length, name, sizeof (name) - 1, i);
390 zone[i] = name;
391 }
392 #else
393 tzset();
394
395 auto zonePtr = (const char**) tzname;
396 zone[0] = zonePtr[0];
397 zone[1] = zonePtr[1];
398 #endif
399
401 {
402 zone[0] = zone[1];
403
404 if (zone[0].length() > 3
405 && zone[0].containsIgnoreCase ("daylight")
406 && zone[0].contains ("GMT"))
407 zone[0] = "BST";
408 }
409
410 return zone[0].substring (0, 3);
411}
412
413int Time::getUTCOffsetSeconds() const noexcept
414{
415 return TimeHelpers::getUTCOffsetSeconds (millisSinceEpoch);
416}
417
418String Time::getUTCOffsetString (bool includeSemiColon) const
419{
420 return TimeHelpers::getUTCOffsetString (getUTCOffsetSeconds(), includeSemiColon);
421}
422
423String Time::toISO8601 (bool includeDividerCharacters) const
424{
425 return String::formatted (includeDividerCharacters ? "%04d-%02d-%02dT%02d:%02d:%06.03f"
426 : "%04d%02d%02dT%02d%02d%06.03f",
427 getYear(),
428 getMonth() + 1,
430 getHours(),
431 getMinutes(),
432 getSeconds() + getMilliseconds() / 1000.0)
433 + getUTCOffsetString (includeDividerCharacters);
434}
435
436static int parseFixedSizeIntAndSkip (String::CharPointerType& t, int numChars, char charToSkip) noexcept
437{
438 int n = 0;
439
440 for (int i = numChars; --i >= 0;)
441 {
442 auto digit = (int) (*t - '0');
443
444 if (! isPositiveAndBelow (digit, 10))
445 return -1;
446
447 ++t;
448 n = n * 10 + digit;
449 }
450
451 if (charToSkip != 0 && *t == (juce_wchar) charToSkip)
452 ++t;
453
454 return n;
455}
456
458{
459 auto t = iso.text;
460 auto year = parseFixedSizeIntAndSkip (t, 4, '-');
461
462 if (year < 0)
463 return {};
464
465 auto month = parseFixedSizeIntAndSkip (t, 2, '-');
466
467 if (month < 0)
468 return {};
469
470 auto day = parseFixedSizeIntAndSkip (t, 2, 0);
471
472 if (day < 0)
473 return {};
474
475 int hours = 0, minutes = 0, milliseconds = 0;
476
477 if (*t == 'T')
478 {
479 ++t;
480 hours = parseFixedSizeIntAndSkip (t, 2, ':');
481
482 if (hours < 0)
483 return {};
484
485 minutes = parseFixedSizeIntAndSkip (t, 2, ':');
486
487 if (minutes < 0)
488 return {};
489
490 auto seconds = parseFixedSizeIntAndSkip (t, 2, 0);
491
492 if (seconds < 0)
493 return {};
494
495 if (*t == '.' || *t == ',')
496 {
497 ++t;
498 milliseconds = parseFixedSizeIntAndSkip (t, 3, 0);
499
500 if (milliseconds < 0)
501 return {};
502 }
503
504 milliseconds += 1000 * seconds;
505 }
506
507 auto nextChar = t.getAndAdvance();
508
509 if (nextChar == '-' || nextChar == '+')
510 {
511 auto offsetHours = parseFixedSizeIntAndSkip (t, 2, ':');
512
513 if (offsetHours < 0)
514 return {};
515
516 auto offsetMinutes = parseFixedSizeIntAndSkip (t, 2, 0);
517
518 if (offsetMinutes < 0)
519 return {};
520
521 auto offsetMs = (offsetHours * 60 + offsetMinutes) * 60 * 1000;
522 milliseconds += nextChar == '-' ? offsetMs : -offsetMs; // NB: this seems backwards but is correct!
523 }
524 else if (nextChar != 0 && nextChar != 'Z')
525 {
526 return {};
527 }
528
529 return Time (year, month - 1, day, hours, minutes, 0, milliseconds, false);
530}
531
532String Time::getMonthName (const bool threeLetterVersion) const
533{
534 return getMonthName (getMonth(), threeLetterVersion);
535}
536
537String Time::getWeekdayName (const bool threeLetterVersion) const
538{
539 return getWeekdayName (getDayOfWeek(), threeLetterVersion);
540}
541
542static const char* const shortMonthNames[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
543static const char* const longMonthNames[] = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" };
544
545String Time::getMonthName (int monthNumber, const bool threeLetterVersion)
546{
547 monthNumber %= 12;
548
549 return TRANS (threeLetterVersion ? shortMonthNames [monthNumber]
550 : longMonthNames [monthNumber]);
551}
552
553String Time::getWeekdayName (int day, const bool threeLetterVersion)
554{
555 static const char* const shortDayNames[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
556 static const char* const longDayNames[] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };
557
558 day %= 7;
559
560 return TRANS (threeLetterVersion ? shortDayNames [day]
561 : longDayNames [day]);
562}
563
564//==============================================================================
565Time& Time::operator+= (RelativeTime delta) noexcept { millisSinceEpoch += delta.inMilliseconds(); return *this; }
566Time& Time::operator-= (RelativeTime delta) noexcept { millisSinceEpoch -= delta.inMilliseconds(); return *this; }
567
568Time operator+ (Time time, RelativeTime delta) noexcept { Time t (time); return t += delta; }
569Time operator- (Time time, RelativeTime delta) noexcept { Time t (time); return t -= delta; }
570Time operator+ (RelativeTime delta, Time time) noexcept { Time t (time); return t += delta; }
571
572RelativeTime operator- (Time time1, Time time2) noexcept { return RelativeTime::milliseconds (time1.toMilliseconds() - time2.toMilliseconds()); }
573
574bool operator== (Time time1, Time time2) noexcept { return time1.toMilliseconds() == time2.toMilliseconds(); }
575bool operator!= (Time time1, Time time2) noexcept { return time1.toMilliseconds() != time2.toMilliseconds(); }
576bool operator< (Time time1, Time time2) noexcept { return time1.toMilliseconds() < time2.toMilliseconds(); }
577bool operator> (Time time1, Time time2) noexcept { return time1.toMilliseconds() > time2.toMilliseconds(); }
578bool operator<= (Time time1, Time time2) noexcept { return time1.toMilliseconds() <= time2.toMilliseconds(); }
579bool operator>= (Time time1, Time time2) noexcept { return time1.toMilliseconds() >= time2.toMilliseconds(); }
580
581static int getMonthNumberForCompileDate (const String& m)
582{
583 for (int i = 0; i < 12; ++i)
584 if (m.equalsIgnoreCase (shortMonthNames[i]))
585 return i;
586
587 // If you hit this because your compiler has an unusual __DATE__
588 // format, let us know so we can add support for it!
589 jassertfalse;
590 return 0;
591}
592
594{
595 StringArray dateTokens, timeTokens;
596
597 dateTokens.addTokens (__DATE__, true);
598 dateTokens.removeEmptyStrings (true);
599
600 timeTokens.addTokens (__TIME__, ":", StringRef());
601
602 return Time (dateTokens[2].getIntValue(),
603 getMonthNumberForCompileDate (dateTokens[0]),
604 dateTokens[1].getIntValue(),
605 timeTokens[0].getIntValue(),
606 timeTokens[1].getIntValue());
607}
608
609
610//==============================================================================
611//==============================================================================
612#if JUCE_UNIT_TESTS
613
614class TimeTests final : public UnitTest
615{
616public:
617 TimeTests()
618 : UnitTest ("Time", UnitTestCategories::time)
619 {}
620
621 void runTest() override
622 {
623 beginTest ("Time");
624
625 Time t = Time::getCurrentTime();
626 expect (t > Time());
627
628 Thread::sleep (15);
629 expect (Time::getCurrentTime() > t);
630
631 expect (t.getTimeZone().isNotEmpty());
632 expect (t.getUTCOffsetString (true) == "Z" || t.getUTCOffsetString (true).length() == 6);
633 expect (t.getUTCOffsetString (false) == "Z" || t.getUTCOffsetString (false).length() == 5);
634
635 expect (TimeHelpers::getUTCOffsetString (-(3 * 60 + 15) * 60, true) == "-03:15");
636 expect (TimeHelpers::getUTCOffsetString (-(3 * 60 + 30) * 60, true) == "-03:30");
637 expect (TimeHelpers::getUTCOffsetString (-(3 * 60 + 45) * 60, true) == "-03:45");
638
639 expect (TimeHelpers::getUTCOffsetString ((3 * 60 + 15) * 60, true) == "+03:15");
640
641 expect (Time::fromISO8601 (t.toISO8601 (true)) == t);
642 expect (Time::fromISO8601 (t.toISO8601 (false)) == t);
643
644 expect (Time::fromISO8601 ("2016-02-16") == Time (2016, 1, 16, 0, 0, 0, 0, false));
645 expect (Time::fromISO8601 ("20160216Z") == Time (2016, 1, 16, 0, 0, 0, 0, false));
646
647 expect (Time::fromISO8601 ("2016-02-16T15:03:57+00:00") == Time (2016, 1, 16, 15, 3, 57, 0, false));
648 expect (Time::fromISO8601 ("20160216T150357+0000") == Time (2016, 1, 16, 15, 3, 57, 0, false));
649
650 expect (Time::fromISO8601 ("2016-02-16T15:03:57.999+00:00") == Time (2016, 1, 16, 15, 3, 57, 999, false));
651 expect (Time::fromISO8601 ("20160216T150357.999+0000") == Time (2016, 1, 16, 15, 3, 57, 999, false));
652 expect (Time::fromISO8601 ("2016-02-16T15:03:57.999Z") == Time (2016, 1, 16, 15, 3, 57, 999, false));
653 expect (Time::fromISO8601 ("2016-02-16T15:03:57,999Z") == Time (2016, 1, 16, 15, 3, 57, 999, false));
654 expect (Time::fromISO8601 ("20160216T150357.999Z") == Time (2016, 1, 16, 15, 3, 57, 999, false));
655 expect (Time::fromISO8601 ("20160216T150357,999Z") == Time (2016, 1, 16, 15, 3, 57, 999, false));
656
657 expect (Time::fromISO8601 ("2016-02-16T15:03:57.999-02:30") == Time (2016, 1, 16, 17, 33, 57, 999, false));
658 expect (Time::fromISO8601 ("2016-02-16T15:03:57,999-02:30") == Time (2016, 1, 16, 17, 33, 57, 999, false));
659 expect (Time::fromISO8601 ("20160216T150357.999-0230") == Time (2016, 1, 16, 17, 33, 57, 999, false));
660 expect (Time::fromISO8601 ("20160216T150357,999-0230") == Time (2016, 1, 16, 17, 33, 57, 999, false));
661
662 expect (Time (1970, 0, 1, 0, 0, 0, 0, false) == Time (0));
663 expect (Time (2106, 1, 7, 6, 28, 15, 0, false) == Time (4294967295000));
664 expect (Time (2007, 10, 7, 1, 7, 20, 0, false) == Time (1194397640000));
665 expect (Time (2038, 0, 19, 3, 14, 7, 0, false) == Time (2147483647000));
666 expect (Time (2016, 2, 7, 11, 20, 8, 0, false) == Time (1457349608000));
667 expect (Time (1969, 11, 31, 23, 59, 59, 0, false) == Time (-1000));
668 expect (Time (1901, 11, 13, 20, 45, 53, 0, false) == Time (-2147483647000));
669
670 expect (Time (1982, 1, 1, 12, 0, 0, 0, true) + RelativeTime::days (365) == Time (1983, 1, 1, 12, 0, 0, 0, true));
671 expect (Time (1970, 1, 1, 12, 0, 0, 0, true) + RelativeTime::days (365) == Time (1971, 1, 1, 12, 0, 0, 0, true));
672 expect (Time (2038, 1, 1, 12, 0, 0, 0, true) + RelativeTime::days (365) == Time (2039, 1, 1, 12, 0, 0, 0, true));
673
674 expect (Time (1982, 1, 1, 12, 0, 0, 0, false) + RelativeTime::days (365) == Time (1983, 1, 1, 12, 0, 0, 0, false));
675 expect (Time (1970, 1, 1, 12, 0, 0, 0, false) + RelativeTime::days (365) == Time (1971, 1, 1, 12, 0, 0, 0, false));
676 expect (Time (2038, 1, 1, 12, 0, 0, 0, false) + RelativeTime::days (365) == Time (2039, 1, 1, 12, 0, 0, 0, false));
677 }
678};
679
680static TimeTests timeTests;
681
682#endif
683
684} // namespace juce
static RelativeTime milliseconds(int milliseconds) noexcept
static RelativeTime days(double numberOfDays) noexcept
void removeEmptyStrings(bool removeWhitespaceStrings=true)
int addTokens(StringRef stringToTokenise, bool preserveQuotedStrings)
String::CharPointerType text
bool containsIgnoreCase(StringRef text) const noexcept
static String formatted(const String &formatStr, Args... args)
Definition: juce_String.h:920
bool contains(StringRef text) const noexcept
String trimEnd() const
String substring(int startIndex, int endIndex) const
static void JUCE_CALLTYPE sleep(int milliseconds)
static void JUCE_CALLTYPE yield()
bool isDaylightSavingTime() const noexcept
Definition: juce_Time.cpp:373
static uint32 getApproximateMillisecondCounter() noexcept
Definition: juce_Time.cpp:261
String getTimeZone() const
Definition: juce_Time.cpp:378
Time()=default
String getUTCOffsetString(bool includeDividerCharacters) const
Definition: juce_Time.cpp:418
int getHoursInAmPmFormat() const noexcept
Definition: juce_Time.cpp:358
static Time fromISO8601(StringRef iso8601)
Definition: juce_Time.cpp:457
int getMilliseconds() const noexcept
Definition: juce_Time.cpp:356
String getWeekdayName(bool threeLetterVersion) const
Definition: juce_Time.cpp:537
int getDayOfMonth() const noexcept
Definition: juce_Time.cpp:351
static int64 currentTimeMillis() noexcept
Definition: juce_Time.cpp:220
int getUTCOffsetSeconds() const noexcept
Definition: juce_Time.cpp:413
int getMonth() const noexcept
Definition: juce_Time.cpp:349
static Time JUCE_CALLTYPE getCurrentTime() noexcept
Definition: juce_Time.cpp:233
String toString(bool includeDate, bool includeTime, bool includeSeconds=true, bool use24HourClock=false) const
Definition: juce_Time.cpp:304
bool isAfternoon() const noexcept
Definition: juce_Time.cpp:368
Time & operator-=(RelativeTime delta) noexcept
Definition: juce_Time.cpp:566
int getYear() const noexcept
Definition: juce_Time.cpp:348
static Time getCompilationDate()
Definition: juce_Time.cpp:593
static double highResolutionTicksToSeconds(int64 ticks) noexcept
Definition: juce_Time.cpp:293
int getDayOfYear() const noexcept
Definition: juce_Time.cpp:350
static int64 secondsToHighResolutionTicks(double seconds) noexcept
Definition: juce_Time.cpp:298
String getMonthName(bool threeLetterVersion) const
Definition: juce_Time.cpp:532
int getMinutes() const noexcept
Definition: juce_Time.cpp:354
Time & operator+=(RelativeTime delta) noexcept
Definition: juce_Time.cpp:565
static void waitForMillisecondCounter(uint32 targetTime) noexcept
Definition: juce_Time.cpp:267
String formatted(const String &format) const
Definition: juce_Time.cpp:341
String toISO8601(bool includeDividerCharacters) const
Definition: juce_Time.cpp:423
int getHours() const noexcept
Definition: juce_Time.cpp:353
static uint32 getMillisecondCounter() noexcept
Definition: juce_Time.cpp:241
int getSeconds() const noexcept
Definition: juce_Time.cpp:355
int getDayOfWeek() const noexcept
Definition: juce_Time.cpp:352