OpenShot Audio Library | OpenShotAudio  0.6.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 
23 namespace juce
24 {
25 
26 namespace 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 //==============================================================================
199 Time::Time (int64 ms) noexcept : millisSinceEpoch (ms) {}
200 
201 Time::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 //==============================================================================
220 int64 Time::currentTimeMillis() noexcept
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 
233 Time JUCE_CALLTYPE Time::getCurrentTime() noexcept
234 {
235  return Time (currentTimeMillis());
236 }
237 
238 //==============================================================================
239 uint32 juce_millisecondsSinceStartup() noexcept;
240 
241 uint32 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 
267 void 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;)
287  Thread::yield();
288  }
289  }
290 }
291 
292 //==============================================================================
293 double Time::highResolutionTicksToSeconds (const int64 ticks) noexcept
294 {
295  return (double) ticks / (double) getHighResolutionTicksPerSecond();
296 }
297 
298 int64 Time::secondsToHighResolutionTicks (const double seconds) noexcept
299 {
300  return (int64) (seconds * (double) getHighResolutionTicksPerSecond());
301 }
302 
303 //==============================================================================
304 String 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 
341 String Time::formatted (const String& format) const
342 {
343  std::tm t (TimeHelpers::millisToLocal (millisSinceEpoch));
344  return TimeHelpers::formatString (format, &t);
345 }
346 
347 //==============================================================================
348 int Time::getYear() const noexcept { return TimeHelpers::millisToLocal (millisSinceEpoch).tm_year + 1900; }
349 int Time::getMonth() const noexcept { return TimeHelpers::millisToLocal (millisSinceEpoch).tm_mon; }
350 int Time::getDayOfYear() const noexcept { return TimeHelpers::millisToLocal (millisSinceEpoch).tm_yday; }
351 int Time::getDayOfMonth() const noexcept { return TimeHelpers::millisToLocal (millisSinceEpoch).tm_mday; }
352 int Time::getDayOfWeek() const noexcept { return TimeHelpers::millisToLocal (millisSinceEpoch).tm_wday; }
353 int Time::getHours() const noexcept { return TimeHelpers::millisToLocal (millisSinceEpoch).tm_hour; }
354 int Time::getMinutes() const noexcept { return TimeHelpers::millisToLocal (millisSinceEpoch).tm_min; }
355 int Time::getSeconds() const noexcept { return TimeHelpers::extendedModulo (millisSinceEpoch / 1000, 60); }
356 int Time::getMilliseconds() const noexcept { return TimeHelpers::extendedModulo (millisSinceEpoch, 1000); }
357 
358 int 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 
368 bool Time::isAfternoon() const noexcept
369 {
370  return getHours() >= 12;
371 }
372 
373 bool 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 
400  if (isDaylightSavingTime())
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 
413 int Time::getUTCOffsetSeconds() const noexcept
414 {
415  return TimeHelpers::getUTCOffsetSeconds (millisSinceEpoch);
416 }
417 
418 String Time::getUTCOffsetString (bool includeSemiColon) const
419 {
420  return TimeHelpers::getUTCOffsetString (getUTCOffsetSeconds(), includeSemiColon);
421 }
422 
423 String 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,
429  getDayOfMonth(),
430  getHours(),
431  getMinutes(),
432  getSeconds() + getMilliseconds() / 1000.0)
433  + getUTCOffsetString (includeDividerCharacters);
434 }
435 
436 static 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 
532 String Time::getMonthName (const bool threeLetterVersion) const
533 {
534  return getMonthName (getMonth(), threeLetterVersion);
535 }
536 
537 String Time::getWeekdayName (const bool threeLetterVersion) const
538 {
539  return getWeekdayName (getDayOfWeek(), threeLetterVersion);
540 }
541 
542 static const char* const shortMonthNames[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
543 static const char* const longMonthNames[] = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" };
544 
545 String Time::getMonthName (int monthNumber, const bool threeLetterVersion)
546 {
547  monthNumber %= 12;
548 
549  return TRANS (threeLetterVersion ? shortMonthNames [monthNumber]
550  : longMonthNames [monthNumber]);
551 }
552 
553 String 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 //==============================================================================
565 Time& Time::operator+= (RelativeTime delta) noexcept { millisSinceEpoch += delta.inMilliseconds(); return *this; }
566 Time& Time::operator-= (RelativeTime delta) noexcept { millisSinceEpoch -= delta.inMilliseconds(); return *this; }
567 
568 Time operator+ (Time time, RelativeTime delta) noexcept { Time t (time); return t += delta; }
569 Time operator- (Time time, RelativeTime delta) noexcept { Time t (time); return t -= delta; }
570 Time operator+ (RelativeTime delta, Time time) noexcept { Time t (time); return t += delta; }
571 
572 RelativeTime operator- (Time time1, Time time2) noexcept { return RelativeTime::milliseconds (time1.toMilliseconds() - time2.toMilliseconds()); }
573 
574 bool operator== (Time time1, Time time2) noexcept { return time1.toMilliseconds() == time2.toMilliseconds(); }
575 bool operator!= (Time time1, Time time2) noexcept { return time1.toMilliseconds() != time2.toMilliseconds(); }
576 bool operator< (Time time1, Time time2) noexcept { return time1.toMilliseconds() < time2.toMilliseconds(); }
577 bool operator> (Time time1, Time time2) noexcept { return time1.toMilliseconds() > time2.toMilliseconds(); }
578 bool operator<= (Time time1, Time time2) noexcept { return time1.toMilliseconds() <= time2.toMilliseconds(); }
579 bool operator>= (Time time1, Time time2) noexcept { return time1.toMilliseconds() >= time2.toMilliseconds(); }
580 
581 static 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 
614 class TimeTests final : public UnitTest
615 {
616 public:
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 
680 static 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