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 inline 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 inline bool isLeapYear (
int year)
noexcept
131 return (year % 400 == 0) || ((year % 100 != 0) && (year % 4 == 0));
134 static inline 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 inline int64 daysFromYear0 (
int year)
noexcept
145 return 365 * year + (year / 400) - (year / 100) + (year / 4);
148 static inline int64 daysFrom1970 (
int year)
noexcept
150 return daysFromYear0 (year) - daysFromYear0 (1970);
153 static inline 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 inline 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 };
187 int hours,
int minutes,
int seconds,
int milliseconds,
188 bool useLocalTime)
noexcept
191 t.tm_year = year - 1900;
199 millisSinceEpoch = 1000 * (useLocalTime ? (int64) mktime (&t)
200 : TimeHelpers::mktime_utc (t))
207 #if JUCE_WINDOWS && ! JUCE_MINGW
210 return ((int64) t.time) * 1000 + t.millitm;
213 gettimeofday (&tv,
nullptr);
214 return ((int64) tv.tv_sec) * 1000 + tv.tv_usec / 1000;
224uint32 juce_millisecondsSinceStartup() noexcept;
226uint32
Time::getMillisecondCounter() noexcept
228 auto now = juce_millisecondsSinceStartup();
230 if (now < TimeHelpers::lastMSCounterValue.get())
235 if (now < TimeHelpers::lastMSCounterValue.get() - (uint32) 1000)
236 TimeHelpers::lastMSCounterValue = now;
240 TimeHelpers::lastMSCounterValue = now;
248 auto t = TimeHelpers::lastMSCounterValue.get();
256 auto now = getMillisecondCounter();
258 if (now >= targetTime)
261 auto toWait = (int) (targetTime - now);
271 for (
int i = 10; --i >= 0;)
280 return ticks / (double) getHighResolutionTicksPerSecond();
285 return (int64) (seconds * (double) getHighResolutionTicksPerSecond());
292 bool use24HourClock)
const
311 << (mins < 10 ?
":0" :
":") << mins;
316 result << (secs < 10 ?
":0" :
":") << secs;
319 if (! use24HourClock)
328 std::tm t (TimeHelpers::millisToLocal (millisSinceEpoch));
329 return TimeHelpers::formatString (format, &t);
333int Time::getYear() const noexcept {
return TimeHelpers::millisToLocal (millisSinceEpoch).tm_year + 1900; }
334int Time::getMonth() const noexcept {
return TimeHelpers::millisToLocal (millisSinceEpoch).tm_mon; }
335int Time::getDayOfYear() const noexcept {
return TimeHelpers::millisToLocal (millisSinceEpoch).tm_yday; }
337int Time::getDayOfWeek() const noexcept {
return TimeHelpers::millisToLocal (millisSinceEpoch).tm_wday; }
338int Time::getHours() const noexcept {
return TimeHelpers::millisToLocal (millisSinceEpoch).tm_hour; }
339int Time::getMinutes() const noexcept {
return TimeHelpers::millisToLocal (millisSinceEpoch).tm_min; }
340int Time::getSeconds() const noexcept {
return TimeHelpers::extendedModulo (millisSinceEpoch / 1000, 60); }
347 if (hours == 0)
return 12;
348 if (hours <= 12)
return hours;
360 return TimeHelpers::millisToLocal (millisSinceEpoch).tm_isdst != 0;
368 #if JUCE_MSVC || JUCE_CLANG
371 for (
int i = 0; i < 2; ++i)
373 char name[128] = { 0 };
375 _get_tzname (&length, name,
sizeof (name) - 1, i);
379 #warning "Can't find a replacement for tzset on mingw - ideas welcome!"
384 auto zonePtr = (
const char**) tzname;
385 zone[0] = zonePtr[0];
386 zone[1] = zonePtr[1];
393 if (zone[0].length() > 3
404 return TimeHelpers::getUTCOffsetSeconds (millisSinceEpoch);
411 auto minutes = seconds / 60;
424 return String::formatted (includeDividerCharacters ?
"%04d-%02d-%02dT%02d:%02d:%06.03f"
425 :
"%04d%02d%02dT%02d%02d%06.03f",
439 for (
int i = numChars; --i >= 0;)
441 auto digit = (int) (*t -
'0');
443 if (! isPositiveAndBelow (digit, 10))
450 if (charToSkip != 0 && *t == (juce_wchar) charToSkip)
459 auto year = parseFixedSizeIntAndSkip (t, 4,
'-');
464 auto month = parseFixedSizeIntAndSkip (t, 2,
'-');
469 auto day = parseFixedSizeIntAndSkip (t, 2, 0);
474 int hours = 0, minutes = 0, milliseconds = 0;
479 hours = parseFixedSizeIntAndSkip (t, 2,
':');
484 minutes = parseFixedSizeIntAndSkip (t, 2,
':');
489 auto seconds = parseFixedSizeIntAndSkip (t, 2, 0);
497 milliseconds = parseFixedSizeIntAndSkip (t, 3, 0);
499 if (milliseconds < 0)
503 milliseconds += 1000 * seconds;
506 auto nextChar = t.getAndAdvance();
508 if (nextChar ==
'-' || nextChar ==
'+')
510 auto offsetHours = parseFixedSizeIntAndSkip (t, 2,
':');
515 auto offsetMinutes = parseFixedSizeIntAndSkip (t, 2, 0);
517 if (offsetMinutes < 0)
520 auto offsetMs = (offsetHours * 60 + offsetMinutes) * 60 * 1000;
521 milliseconds += nextChar ==
'-' ? offsetMs : -offsetMs;
523 else if (nextChar != 0 && nextChar !=
'Z')
528 return Time (year, month - 1, day, hours, minutes, 0, milliseconds,
false);
541static const char*
const shortMonthNames[] = {
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec" };
542static const char*
const longMonthNames[] = {
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December" };
548 return TRANS (threeLetterVersion ? shortMonthNames [monthNumber]
549 : longMonthNames [monthNumber]);
554 static const char*
const shortDayNames[] = {
"Sun",
"Mon",
"Tue",
"Wed",
"Thu",
"Fri",
"Sat" };
555 static const char*
const longDayNames[] = {
"Sunday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday" };
559 return TRANS (threeLetterVersion ? shortDayNames [day]
560 : longDayNames [day]);
568Time operator- (Time time, RelativeTime delta)
noexcept { Time t (time);
return t -= delta; }
569Time operator+ (RelativeTime delta, Time time)
noexcept { Time t (time);
return t += delta; }
570const RelativeTime operator- (Time time1, Time time2)
noexcept {
return RelativeTime::milliseconds (time1.toMilliseconds() - time2.toMilliseconds()); }
572bool operator== (Time time1, Time time2)
noexcept {
return time1.toMilliseconds() == time2.toMilliseconds(); }
573bool operator!= (Time time1, Time time2)
noexcept {
return 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(); }
579static int getMonthNumberForCompileDate (
const String& m)
581 for (
int i = 0; i < 12; ++i)
582 if (m.equalsIgnoreCase (shortMonthNames[i]))
600 return Time (dateTokens[2].getIntValue(),
601 getMonthNumberForCompileDate (dateTokens[0]),
602 dateTokens[1].getIntValue(),
603 timeTokens[0].getIntValue(),
604 timeTokens[1].getIntValue());
615 TimeTests() :
UnitTest (
"Time",
"Time") {}
617 void runTest()
override
621 Time t = Time::getCurrentTime();
625 expect (Time::getCurrentTime() > t);
627 expect (t.getTimeZone().isNotEmpty());
628 expect (t.getUTCOffsetString (
true) ==
"Z" || t.getUTCOffsetString (
true).length() == 6);
629 expect (t.getUTCOffsetString (
false) ==
"Z" || t.getUTCOffsetString (
false).length() == 5);
631 expect (Time::fromISO8601 (t.toISO8601 (
true)) == t);
632 expect (Time::fromISO8601 (t.toISO8601 (
false)) == t);
634 expect (Time::fromISO8601 (
"2016-02-16") == Time (2016, 1, 16, 0, 0, 0, 0,
false));
635 expect (Time::fromISO8601 (
"20160216Z") == Time (2016, 1, 16, 0, 0, 0, 0,
false));
636 expect (Time::fromISO8601 (
"2016-02-16T15:03:57+00:00") == Time (2016, 1, 16, 15, 3, 57, 0,
false));
637 expect (Time::fromISO8601 (
"20160216T150357+0000") == Time (2016, 1, 16, 15, 3, 57, 0,
false));
638 expect (Time::fromISO8601 (
"2016-02-16T15:03:57.999+00:00") == Time (2016, 1, 16, 15, 3, 57, 999,
false));
639 expect (Time::fromISO8601 (
"20160216T150357.999+0000") == Time (2016, 1, 16, 15, 3, 57, 999,
false));
640 expect (Time::fromISO8601 (
"2016-02-16T15:03:57.999Z") == Time (2016, 1, 16, 15, 3, 57, 999,
false));
641 expect (Time::fromISO8601 (
"20160216T150357.999Z") == Time (2016, 1, 16, 15, 3, 57, 999,
false));
642 expect (Time::fromISO8601 (
"2016-02-16T15:03:57.999-02:30") == Time (2016, 1, 16, 17, 33, 57, 999,
false));
643 expect (Time::fromISO8601 (
"20160216T150357.999-0230") == Time (2016, 1, 16, 17, 33, 57, 999,
false));
645 expect (Time (1970, 0, 1, 0, 0, 0, 0,
false) == Time (0));
646 expect (Time (2106, 1, 7, 6, 28, 15, 0,
false) == Time (4294967295000));
647 expect (Time (2007, 10, 7, 1, 7, 20, 0,
false) == Time (1194397640000));
648 expect (Time (2038, 0, 19, 3, 14, 7, 0,
false) == Time (2147483647000));
649 expect (Time (2016, 2, 7, 11, 20, 8, 0,
false) == Time (1457349608000));
650 expect (Time (1969, 11, 31, 23, 59, 59, 0,
false) == Time (-1000));
651 expect (Time (1901, 11, 13, 20, 45, 53, 0,
false) == Time (-2147483647000));
653 expect (Time (1982, 1, 1, 12, 0, 0, 0,
true) + RelativeTime::days (365) == Time (1983, 1, 1, 12, 0, 0, 0,
true));
654 expect (Time (1970, 1, 1, 12, 0, 0, 0,
true) + RelativeTime::days (365) == Time (1971, 1, 1, 12, 0, 0, 0,
true));
655 expect (Time (2038, 1, 1, 12, 0, 0, 0,
true) + RelativeTime::days (365) == Time (2039, 1, 1, 12, 0, 0, 0,
true));
657 expect (Time (1982, 1, 1, 12, 0, 0, 0,
false) + RelativeTime::days (365) == Time (1983, 1, 1, 12, 0, 0, 0,
false));
658 expect (Time (1970, 1, 1, 12, 0, 0, 0,
false) + RelativeTime::days (365) == Time (1971, 1, 1, 12, 0, 0, 0,
false));
659 expect (Time (2038, 1, 1, 12, 0, 0, 0,
false) + RelativeTime::days (365) == Time (2039, 1, 1, 12, 0, 0, 0,
false));
663static TimeTests timeTests;
Wraps a pointer to a null-terminated UTF-8 character string, and provides various methods to operate ...
A relative measure of time.
static RelativeTime milliseconds(int milliseconds) noexcept
Creates a new RelativeTime object representing a number of milliseconds.
A special array for holding a list of strings.
void removeEmptyStrings(bool removeWhitespaceStrings=true)
Removes empty strings from the array.
int addTokens(StringRef stringToTokenise, bool preserveQuotedStrings)
Breaks up a string into tokens and adds them to this array.
A simple class for holding temporary references to a string literal or String.
String::CharPointerType text
The text that is referenced.
bool containsIgnoreCase(StringRef text) const noexcept
Tests whether the string contains another substring.
static String formatted(const String &formatStr, Args... args)
Creates a String from a printf-style parameter list.
bool contains(StringRef text) const noexcept
Tests whether the string contains another substring.
String trimEnd() const
Returns a copy of this string with any whitespace characters removed from the end.
String substring(int startIndex, int endIndex) const
Returns a subsection of the string.
static void JUCE_CALLTYPE sleep(int milliseconds)
Suspends the execution of the current thread until the specified timeout period has elapsed (note tha...
static void JUCE_CALLTYPE yield()
Yields the current thread's CPU time-slot and allows a new thread to run.
Holds an absolute date and time.
bool isDaylightSavingTime() const noexcept
Returns true if the local timezone uses a daylight saving correction.
static uint32 getApproximateMillisecondCounter() noexcept
Less-accurate but faster version of getMillisecondCounter().
String getTimeZone() const
Returns a 3-character string to indicate the local timezone.
Time()=default
Creates a Time object.
String getUTCOffsetString(bool includeDividerCharacters) const
Returns a string to indicate the offset of the local timezone from UTC.
int getHoursInAmPmFormat() const noexcept
Returns the hours in 12-hour clock format (in this machine's local timezone).
static Time fromISO8601(StringRef iso8601)
Parses an ISO-8601 string and returns it as a Time.
int getMilliseconds() const noexcept
Returns the number of milliseconds, 0 to 999.
String getWeekdayName(bool threeLetterVersion) const
Returns the name of the weekday (in this machine's local timezone).
int getDayOfMonth() const noexcept
Returns the day of the month (in this machine's local timezone).
static int64 currentTimeMillis() noexcept
Returns the current system time.
int getUTCOffsetSeconds() const noexcept
Returns the local timezone offset from UTC in seconds.
int getMonth() const noexcept
Returns the number of the month (in this machine's local timezone).
static Time JUCE_CALLTYPE getCurrentTime() noexcept
Returns a Time object that is set to the current system time.
String toString(bool includeDate, bool includeTime, bool includeSeconds=true, bool use24HourClock=false) const
Returns a string version of this date and time, using this machine's local timezone.
bool isAfternoon() const noexcept
Returns true if the time is in the afternoon (in this machine's local timezone).
Time & operator-=(RelativeTime delta) noexcept
Subtracts a RelativeTime from this time.
int getYear() const noexcept
Returns the year (in this machine's local timezone).
static Time getCompilationDate()
Returns a Time based on the value of the DATE macro when this module was compiled.
static double highResolutionTicksToSeconds(int64 ticks) noexcept
Converts a number of high-resolution ticks into seconds.
int getDayOfYear() const noexcept
Returns the number of the day of the year (in this machine's local timezone).
static int64 secondsToHighResolutionTicks(double seconds) noexcept
Converts a number seconds into high-resolution ticks.
String getMonthName(bool threeLetterVersion) const
Returns the name of the month (in this machine's local timezone).
int getMinutes() const noexcept
Returns the number of minutes, 0 to 59 (in this machine's local timezone).
Time & operator+=(RelativeTime delta) noexcept
Adds a RelativeTime to this time.
static void waitForMillisecondCounter(uint32 targetTime) noexcept
Waits until the getMillisecondCounter() reaches a given value.
String formatted(const String &format) const
Converts this date/time to a string with a user-defined format.
String toISO8601(bool includeDividerCharacters) const
Returns a fully described string of this date and time in ISO-8601 format (using the local timezone).
int getHours() const noexcept
Returns the number of hours since midnight (in this machine's local timezone).
static uint32 getMillisecondCounter() noexcept
Returns the number of millisecs since a fixed event (usually system startup).
int getSeconds() const noexcept
Returns the number of seconds, 0 to 59.
int getDayOfWeek() const noexcept
Returns the number of the day of the week (in this machine's local timezone).
This is a base class for classes that perform a unit test.