28 static std::tm millisToLocal (int64 millis)
noexcept
30 #if JUCE_WINDOWS && JUCE_MINGW
31 auto now = (time_t) (millis / 1000);
32 return *localtime (&now);
38 if (_localtime64_s (&result, &millis) != 0)
45 auto now = (time_t) (millis / 1000);
47 if (localtime_r (&now, &result) ==
nullptr)
54 static std::tm millisToUTC (int64 millis)
noexcept
56 #if JUCE_WINDOWS && JUCE_MINGW
57 auto now = (time_t) (millis / 1000);
58 return *gmtime (&now);
64 if (_gmtime64_s (&result, &millis) != 0)
71 auto now = (time_t) (millis / 1000);
73 if (gmtime_r (&now, &result) ==
nullptr)
80 static int getUTCOffsetSeconds (
const int64 millis)
noexcept
82 auto utc = millisToUTC (millis);
85 return (
int) ((millis / 1000) - (int64) mktime (&utc));
88 static int extendedModulo (
const int64 value,
const int modulo)
noexcept
90 return (
int) (value >= 0 ? (value % modulo)
91 : (value - ((value / modulo) + 1) * modulo));
94 static String formatString (
const String& format,
const std::tm*
const tm)
97 using StringType = CharPointer_UTF8;
99 using StringType = CharPointer_UTF16;
101 using StringType = CharPointer_UTF32;
105 if (tm->tm_year < -1900 || tm->tm_year > 8099)
109 for (
size_t bufferSize = 256; ; bufferSize += 256)
111 HeapBlock<StringType::CharType> buffer (bufferSize);
115 strftime (buffer, bufferSize - 1, format.toUTF8(), tm);
117 wcsftime (buffer, bufferSize - 1, format.toWideCharPointer(), tm);
119 wcsftime (buffer, bufferSize - 1, format.toUTF32(), tm);
122 if (numChars > 0 || format.isEmpty())
123 return String (StringType (buffer),
124 StringType (buffer) + (
int) numChars);
129 static bool isLeapYear (
int year)
noexcept
131 return (year % 400 == 0) || ((year % 100 != 0) && (year % 4 == 0));
134 static int daysFromJan1 (
int year,
int month)
noexcept
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 };
139 return dayOfYear [(isLeapYear (year) ? 12 : 0) + month];
142 static int64 daysFromYear0 (
int year)
noexcept
145 return 365 * year + (year / 400) - (year / 100) + (year / 4);
148 static int64 daysFrom1970 (
int year)
noexcept
150 return daysFromYear0 (year) - daysFromYear0 (1970);
153 static int64 daysFrom1970 (
int year,
int month)
noexcept
162 auto numYears = (11 - month) / 12;
164 month += 12 * numYears;
167 return daysFrom1970 (year) + daysFromJan1 (year, month);
172 static int64 mktime_utc (
const std::tm& t)
noexcept
174 return 24 * 3600 * (daysFrom1970 (t.tm_year + 1900, t.tm_mon) + (t.tm_mday - 1))
180 static Atomic<uint32> lastMSCounterValue { (uint32) 0 };
182 static String getUTCOffsetString (
int utcOffsetSeconds,
bool includeSemiColon)
184 if (
const auto seconds = utcOffsetSeconds)
186 auto minutes = seconds / 60;
202 int hours,
int minutes,
int seconds,
int milliseconds,
206 t.tm_year =
year - 1900;
215 : TimeHelpers::mktime_utc (
t))
222 #if JUCE_WINDOWS && ! JUCE_MINGW
225 return ((int64)
t.time) * 1000 +
t.millitm;
229 return ((int64)
tv.tv_sec) * 1000 +
tv.tv_usec / 1000;
239uint32 juce_millisecondsSinceStartup()
noexcept;
243 auto now = juce_millisecondsSinceStartup();
245 if (
now < TimeHelpers::lastMSCounterValue.get())
250 if (
now < TimeHelpers::lastMSCounterValue.get() - (uint32) 1000)
251 TimeHelpers::lastMSCounterValue =
now;
255 TimeHelpers::lastMSCounterValue =
now;
263 auto t = TimeHelpers::lastMSCounterValue.get();
271 auto now = getMillisecondCounter();
286 for (
int i = 10; --i >= 0;)
295 return (
double)
ticks / (
double) getHighResolutionTicksPerSecond();
300 return (int64) (seconds * (
double) getHighResolutionTicksPerSecond());
326 << (
mins < 10 ?
":0" :
":") <<
mins;
331 result << (
secs < 10 ?
":0" :
":") <<
secs;
343 std::tm
t (TimeHelpers::millisToLocal (millisSinceEpoch));
344 return TimeHelpers::formatString (format, &
t);
362 if (hours == 0)
return 12;
363 if (hours <= 12)
return hours;
375 return TimeHelpers::millisToLocal (millisSinceEpoch).tm_isdst != 0;
382 #if JUCE_WINDOWS && (JUCE_MSVC || JUCE_CLANG)
385 for (
int i = 0; i < 2; ++i)
387 char name[128] = { 0 };
404 if (zone[0].length() > 3
415 return TimeHelpers::getUTCOffsetSeconds (millisSinceEpoch);
426 :
"%04d%02d%02dT%02d%02d%06.03f",
436static int parseFixedSizeIntAndSkip (String::CharPointerType&
t,
int numChars,
char charToSkip)
noexcept
444 if (! isPositiveAndBelow (
digit, 10))
451 if (charToSkip != 0 && *t == (juce_wchar) charToSkip)
460 auto year = parseFixedSizeIntAndSkip (
t, 4,
'-');
465 auto month = parseFixedSizeIntAndSkip (
t, 2,
'-');
470 auto day = parseFixedSizeIntAndSkip (
t, 2, 0);
475 int hours = 0, minutes = 0, milliseconds = 0;
480 hours = parseFixedSizeIntAndSkip (
t, 2,
':');
485 minutes = parseFixedSizeIntAndSkip (
t, 2,
':');
490 auto seconds = parseFixedSizeIntAndSkip (
t, 2, 0);
495 if (*
t ==
'.' || *
t ==
',')
498 milliseconds = parseFixedSizeIntAndSkip (
t, 3, 0);
500 if (milliseconds < 0)
504 milliseconds += 1000 * seconds;
511 auto offsetHours = parseFixedSizeIntAndSkip (
t, 2,
':');
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" };
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" };
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; }
572RelativeTime operator- (Time time1, Time time2)
noexcept {
return RelativeTime::milliseconds (time1.toMilliseconds() - time2.toMilliseconds()); }
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(); }
581static int getMonthNumberForCompileDate (
const String& m)
583 for (
int i = 0; i < 12; ++i)
584 if (m.equalsIgnoreCase (shortMonthNames[i]))
618 :
UnitTest (
"Time", UnitTestCategories::time)
621 void runTest()
override
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);
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");
639 expect (TimeHelpers::getUTCOffsetString ((3 * 60 + 15) * 60,
true) ==
"+03:15");
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));
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));
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));
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));
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));
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));
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));
680static TimeTests timeTests;
static RelativeTime milliseconds(int milliseconds) noexcept
static RelativeTime days(double numberOfDays) noexcept
bool containsIgnoreCase(StringRef text) const noexcept
static String formatted(const String &formatStr, Args... args)
bool contains(StringRef text) const noexcept
String substring(int startIndex, int endIndex) const
static void JUCE_CALLTYPE sleep(int milliseconds)
static void JUCE_CALLTYPE yield()
bool isDaylightSavingTime() const noexcept
static uint32 getApproximateMillisecondCounter() noexcept
String getTimeZone() const
String getUTCOffsetString(bool includeDividerCharacters) const
int getHoursInAmPmFormat() const noexcept
static Time fromISO8601(StringRef iso8601)
int getMilliseconds() const noexcept
String getWeekdayName(bool threeLetterVersion) const
int getDayOfMonth() const noexcept
static int64 currentTimeMillis() noexcept
int getUTCOffsetSeconds() const noexcept
int getMonth() const noexcept
static Time JUCE_CALLTYPE getCurrentTime() noexcept
String toString(bool includeDate, bool includeTime, bool includeSeconds=true, bool use24HourClock=false) const
bool isAfternoon() const noexcept
Time & operator-=(RelativeTime delta) noexcept
int getYear() const noexcept
static Time getCompilationDate()
static double highResolutionTicksToSeconds(int64 ticks) noexcept
int getDayOfYear() const noexcept
static int64 secondsToHighResolutionTicks(double seconds) noexcept
String getMonthName(bool threeLetterVersion) const
int getMinutes() const noexcept
Time & operator+=(RelativeTime delta) noexcept
static void waitForMillisecondCounter(uint32 targetTime) noexcept
String formatted(const String &format) const
String toISO8601(bool includeDividerCharacters) const
int getHours() const noexcept
static uint32 getMillisecondCounter() noexcept
int getSeconds() const noexcept
int getDayOfWeek() const noexcept