15 #include <CoreFoundation/CoreFoundation.h>
25 "title" :
"Date-Time",
26 "description" :
"A date and time.",
45 return json_object_get_double(js);
53 return json_object_new_double(value);
67 bool ret =
VuoTime_getComponents(value, &year, NULL, &month, &dayOfMonth, NULL, NULL, &hour, &minute, &second);
69 return VuoText_format(
"%04lld-%02lld-%02lld %02lld:%02lld:%05.02f", year, month, dayOfMonth, hour, minute, second);
71 return strdup(
"Unknown");
79 return valueA == valueB;
87 return valueA < valueB;
97 for (
int i = 1; i <= timeCount; ++i)
107 for (
int i = 1; i <= timeCount; ++i)
110 if (fabs(t - minimumTime) > toleranceInSeconds)
122 return fmod(time, 86400);
135 VuoTime minimumTime = INFINITY;
137 for (
int i = 1; i <= timeCount; ++i)
147 for (
int i = 1; i <= timeCount; ++i)
150 if (fabs(t - minimumTime) > toleranceInSeconds
151 && fabs(t - 86400 - minimumTime) > toleranceInSeconds)
170 timeOnlyA = fmod(86400 + timeOnlyA - timeOnlyStart, 86400);
171 timeOnlyB = fmod(86400 + timeOnlyB - timeOnlyStart, 86400);
173 return timeOnlyA < timeOnlyB;
187 gettimeofday(&now, NULL);
196 return (year % 4 == 0)
197 && !((year % 100 == 0)
198 && (year % 400 != 0));
209 tm.tm_year = year - 1900;
210 tm.tm_mon = month - 1;
211 tm.tm_mday = dayOfMonth;
216 time_t timeInt = mktime(&tm);
223 for (
int y = year; y < 1970; (year<1970 ? ++y : --y))
228 char daysPerMonth[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
231 for (
int m = 0; m < month-1; ++m)
232 dayOfYear += daysPerMonth[m];
233 dayOfYear += dayOfMonth;
236 && dayOfYear > 31 + 28)
247 time_t t = time(NULL);
248 struct tm lt = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL};
249 localtime_r(&t, <);
250 timeInt -= lt.tm_gmtoff;
261 const char *dateFormatString = nl_langinfo_l(D_FMT, locale);
262 const char *time12FormatString = nl_langinfo_l(T_FMT_AMPM, locale);
263 const char *time24FormatString = nl_langinfo_l(T_FMT, locale);
265 if (format == VuoTimeFormat_DateTimeShort12)
266 return VuoText_format(
"%s %s", dateFormatString, time12FormatString);
267 else if (format == VuoTimeFormat_DateTimeShort24)
268 return VuoText_format(
"%s %s", dateFormatString, time24FormatString);
269 else if (format == VuoTimeFormat_DateTimeMedium12)
271 else if (format == VuoTimeFormat_DateTimeMedium24)
273 else if (format == VuoTimeFormat_DateTimeLong12)
274 return VuoText_format(
"%%A, %%B %%e, %%Y %s", time12FormatString);
275 else if (format == VuoTimeFormat_DateTimeLong24)
276 return VuoText_format(
"%%A, %%B %%e, %%Y %s", time24FormatString);
277 else if (format == VuoTimeFormat_DateTimeSortable)
278 return strdup(
"%Y-%m-%d %H:%M:%SZ");
279 else if (format == VuoTimeFormat_DateShort)
280 return strdup(dateFormatString);
281 else if (format == VuoTimeFormat_DateMedium)
282 return strdup(
"%b %e, %Y");
283 else if (format == VuoTimeFormat_DateLong)
284 return strdup(
"%A, %B %e, %Y");
285 else if (format == VuoTimeFormat_Time12)
286 return strdup(time12FormatString);
287 else if (format == VuoTimeFormat_Time24)
288 return strdup(time24FormatString);
305 for (
int i = 0; i < numFormats; ++i)
310 bzero(&tm,
sizeof(
struct tm));
312 char *ret = strptime(str, formats[i], &tm);
315 for ( ; *ret != 0 && isspace(*ret); ++ret) {}
323 time_t timeInt = mktime(&tm);
338 const int numFormats = 2;
339 const char *formats[numFormats] = {
340 "%a, %d %b %Y %T %z",
355 const int numFormats = 4;
356 const char *formats[numFormats] = {
357 "%Y-%m-%dT%H:%M:%SZ",
358 "%Y-%m-%d %H:%M:%SZ",
359 "%Y-%m-%dT%H:%M:%S+00:00",
360 "%Y-%m-%d %H:%M:%S+00:00"
371 for (
int i = 0; format[i] != 0; ++i)
372 if (format[i] ==
'Y')
384 CFLocaleRef localeCF = CFLocaleCopyCurrent();
388 locale_t locale = newlocale(LC_ALL_MASK, localeID, NULL);
390 const int numFormats = 15;
391 char *formats[numFormats] = {
413 for (
int i = 0; i < numFormats; ++i)
439 struct tm *tm = localtime(&unixtime);
443 *year = tm->tm_year + 1900;
445 *dayOfYear = tm->tm_yday + 1;
447 *month = tm->tm_mon + 1;
449 *dayOfMonth = tm->tm_mday;
453 strftime(s, 3,
"%V", tm);
457 *dayOfWeek = tm->tm_wday;
461 *minute = tm->tm_min;
465 *second = fmod(time, 60);
467 *second = fmod(60 + fmod(time, 60), 60);
485 bool ret =
VuoTime_getComponents(value, &year, NULL, &month, &dayOfMonth, NULL, &dayOfWeek, &hour, &minute, &second);
489 if (unit == VuoTimeUnit_Millennium)
491 if (roundingMethod == VuoRoundingMethod_Nearest)
492 return VuoTime_make(1000*(year/1000) + (year%1000 > 500 ? 1000 : 0), 1, 1, 0, 0, 0);
493 else if (roundingMethod == VuoRoundingMethod_Down)
495 else if (roundingMethod == VuoRoundingMethod_Up)
496 return VuoTime_make(1000*(year/1000) + (year%1000 + month + dayOfMonth + hour + minute + second > 0 ? 1000 : 0), 1, 1, 0, 0, 0);
498 else if (unit == VuoTimeUnit_Century)
500 if (roundingMethod == VuoRoundingMethod_Nearest)
501 return VuoTime_make(100*(year/100) + (year%100 > 50 ? 100 : 0), 1, 1, 0, 0, 0);
502 else if (roundingMethod == VuoRoundingMethod_Down)
504 else if (roundingMethod == VuoRoundingMethod_Up)
505 return VuoTime_make(100*(year/100) + (year%100 + month + dayOfMonth + hour + minute + second > 0 ? 100 : 0), 1, 1, 0, 0, 0);
507 else if (unit == VuoTimeUnit_Decade)
509 if (roundingMethod == VuoRoundingMethod_Nearest)
510 return VuoTime_make(10*(year/10) + (year%10 > 5 ? 10 : 0), 1, 1, 0, 0, 0);
511 else if (roundingMethod == VuoRoundingMethod_Down)
513 else if (roundingMethod == VuoRoundingMethod_Up)
514 return VuoTime_make(10*(year/10) + (year%10 + month + dayOfMonth + hour + minute + second > 0 ? 10 : 0), 1, 1, 0, 0, 0);
516 else if (unit == VuoTimeUnit_Year)
518 if (roundingMethod == VuoRoundingMethod_Nearest)
519 return VuoTime_make(year + (month > 6 ? 1 : 0), 1, 1, 0, 0, 0);
520 else if (roundingMethod == VuoRoundingMethod_Down)
522 else if (roundingMethod == VuoRoundingMethod_Up)
523 return VuoTime_make(year + (month + dayOfMonth + hour + minute + second > 0 ? 1 : 0), 1, 1, 0, 0, 0);
525 else if (unit == VuoTimeUnit_Quarter)
527 if (roundingMethod == VuoRoundingMethod_Nearest)
528 return VuoTime_make(year, 3*((month-1)/3) + 1 + ((month-1)%3 > 1 ? 3 : 0), 1, 0, 0, 0);
529 else if (roundingMethod == VuoRoundingMethod_Down)
530 return VuoTime_make(year, 3*((month-1)/3) + 1, 1, 0, 0, 0);
531 else if (roundingMethod == VuoRoundingMethod_Up)
532 return VuoTime_make(year, 3*((month-1)/3) + 1 + ((month-1)%3 + dayOfMonth + hour + minute + second > 0 ? 3 : 0), 1, 0, 0, 0);
534 else if (unit == VuoTimeUnit_Month)
536 if (roundingMethod == VuoRoundingMethod_Nearest)
537 return VuoTime_make(year, month + (dayOfMonth > 15 ? 1 : 0), 1, 0, 0, 0);
538 else if (roundingMethod == VuoRoundingMethod_Down)
540 else if (roundingMethod == VuoRoundingMethod_Up)
541 return VuoTime_make(year, month + (dayOfMonth + hour + minute + second > 0 ? 1 : 0), 1, 0, 0, 0);
543 else if (unit == VuoTimeUnit_WeekSunday)
545 if (roundingMethod == VuoRoundingMethod_Nearest)
546 return VuoTime_make(year, month, dayOfMonth + (dayOfWeek > VuoWeekday_Wednesday ? 7-dayOfWeek : -dayOfWeek), 0, 0, 0);
547 else if (roundingMethod == VuoRoundingMethod_Down)
548 return VuoTime_make(year, month, dayOfMonth - dayOfWeek, 0, 0, 0);
549 else if (roundingMethod == VuoRoundingMethod_Up)
550 return VuoTime_make(year, month, dayOfMonth + (dayOfWeek + hour + minute + second > 0 ? 7-dayOfWeek : 0), 0, 0, 0);
552 else if (unit == VuoTimeUnit_WeekMonday)
554 if (dayOfWeek == VuoWeekday_Sunday)
557 if (roundingMethod == VuoRoundingMethod_Nearest)
558 return VuoTime_make(year, month, dayOfMonth + (dayOfWeek > VuoWeekday_Thursday ? 8-dayOfWeek : 1-dayOfWeek), 0, 0, 0);
559 else if (roundingMethod == VuoRoundingMethod_Down)
560 return VuoTime_make(year, month, dayOfMonth - dayOfWeek + 1, 0, 0, 0);
561 else if (roundingMethod == VuoRoundingMethod_Up)
562 return VuoTime_make(year, month, dayOfMonth + (dayOfWeek-1 + hour + minute + second > 0 ? 8-dayOfWeek : 0), 0, 0, 0);
564 else if (unit == VuoTimeUnit_Day)
566 if (roundingMethod == VuoRoundingMethod_Nearest)
567 return VuoTime_make(year, month, dayOfMonth + (hour > 12 ? 1 : 0), 0, 0, 0);
568 else if (roundingMethod == VuoRoundingMethod_Down)
570 else if (roundingMethod == VuoRoundingMethod_Up)
571 return VuoTime_make(year, month, dayOfMonth + (hour + minute + second > 0 ? 1 : 0), 0, 0, 0);
573 else if (unit == VuoTimeUnit_Hour)
575 if (roundingMethod == VuoRoundingMethod_Nearest)
576 return VuoTime_make(year, month, dayOfMonth, hour + (minute > 30 ? 1 : 0), 0, 0);
577 else if (roundingMethod == VuoRoundingMethod_Down)
578 return VuoTime_make(year, month, dayOfMonth, hour, 0, 0);
579 else if (roundingMethod == VuoRoundingMethod_Up)
580 return VuoTime_make(year, month, dayOfMonth, hour + (minute + second > 0 ? 1 : 0), 0, 0);
582 else if (unit == VuoTimeUnit_HalfHour)
584 if (roundingMethod == VuoRoundingMethod_Nearest)
585 return VuoTime_make(year, month, dayOfMonth, hour, 30*(minute/30) + (minute%30 > 15 ? 30 : 0), 0);
586 else if (roundingMethod == VuoRoundingMethod_Down)
587 return VuoTime_make(year, month, dayOfMonth, hour, 30*(minute/30), 0);
588 else if (roundingMethod == VuoRoundingMethod_Up)
589 return VuoTime_make(year, month, dayOfMonth, hour, 30*(minute/30) + (minute%30 + second > 0 ? 30 : 0), 0);
591 else if (unit == VuoTimeUnit_QuarterHour)
593 if (roundingMethod == VuoRoundingMethod_Nearest)
594 return VuoTime_make(year, month, dayOfMonth, hour, 15*(minute/15) + (minute%15 > 7 ? 15 : 0), 0);
595 else if (roundingMethod == VuoRoundingMethod_Down)
596 return VuoTime_make(year, month, dayOfMonth, hour, 15*(minute/15), 0);
597 else if (roundingMethod == VuoRoundingMethod_Up)
598 return VuoTime_make(year, month, dayOfMonth, hour, 15*(minute/15) + (minute%15 + second > 0 ? 15 : 0), 0);
600 else if (unit == VuoTimeUnit_Minute)
602 if (roundingMethod == VuoRoundingMethod_Nearest)
603 return VuoTime_make(year, month, dayOfMonth, hour, minute + (second > 30 ? 1 : 0), 0);
604 else if (roundingMethod == VuoRoundingMethod_Down)
605 return VuoTime_make(year, month, dayOfMonth, hour, minute, 0);
606 else if (roundingMethod == VuoRoundingMethod_Up)
607 return VuoTime_make(year, month, dayOfMonth, hour, minute + (second > 0 ? 1 : 0), 0);
609 else if (unit == VuoTimeUnit_Second)
611 if (roundingMethod == VuoRoundingMethod_Nearest)
612 return lround(value);
613 else if (roundingMethod == VuoRoundingMethod_Down)
615 else if (roundingMethod == VuoRoundingMethod_Up)
631 CFLocaleRef localeCF = CFLocaleCopyCurrent();
640 return formattedTime;
654 locale_t locale = newlocale(LC_ALL_MASK, localeIdentifier, NULL);
655 static dispatch_once_t loggedLocale = 0;
656 dispatch_once(&loggedLocale, ^{
657 VUserLog(
"macOS Locale: %s", localeIdentifier);
658 VUserLog(
" C Locale: %s", querylocale(LC_ALL_MASK, locale));
667 if (format == VuoTimeFormat_DateTimeSortable)
674 char formattedTime[1024];
675 strftime_l(formattedTime, 1024, formatString, tm, locale);