14 #include <CoreFoundation/CoreFoundation.h>
24 "title" :
"Date-Time",
25 "description" :
"A date and time.",
44 return json_object_get_double(js);
52 return json_object_new_double(value);
66 bool ret =
VuoTime_getComponents(value, &year, NULL, &month, &dayOfMonth, NULL, NULL, &hour, &minute, &second);
68 return VuoText_format(
"%04lld-%02lld-%02lld %02lld:%02lld:%05.02f", year, month, dayOfMonth, hour, minute, second);
70 return strdup(
"Unknown");
78 return valueA == valueB;
86 return valueA < valueB;
96 for (
int i = 1; i <= timeCount; ++i)
106 for (
int i = 1; i <= timeCount; ++i)
109 if (fabs(t - minimumTime) > toleranceInSeconds)
121 return fmod(time, 86400);
134 VuoTime minimumTime = INFINITY;
136 for (
int i = 1; i <= timeCount; ++i)
146 for (
int i = 1; i <= timeCount; ++i)
149 if (fabs(t - minimumTime) > toleranceInSeconds
150 && fabs(t - 86400 - minimumTime) > toleranceInSeconds)
169 timeOnlyA = fmod(86400 + timeOnlyA - timeOnlyStart, 86400);
170 timeOnlyB = fmod(86400 + timeOnlyB - timeOnlyStart, 86400);
172 return timeOnlyA < timeOnlyB;
186 gettimeofday(&now, NULL);
195 return (year % 4 == 0)
196 && !((year % 100 == 0)
197 && (year % 400 != 0));
208 tm.tm_year = year - 1900;
209 tm.tm_mon = month - 1;
210 tm.tm_mday = dayOfMonth;
215 time_t timeInt = mktime(&tm);
222 for (
int y = year; y < 1970; (year<1970 ? ++y : --y))
227 char daysPerMonth[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
230 for (
int m = 0; m < month-1; ++m)
231 dayOfYear += daysPerMonth[m];
232 dayOfYear += dayOfMonth;
235 && dayOfYear > 31 + 28)
246 time_t t = time(NULL);
247 struct tm lt = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL};
248 localtime_r(&t, <);
249 timeInt -= lt.tm_gmtoff;
260 const char *dateFormatString = nl_langinfo_l(D_FMT, locale);
261 const char *time12FormatString = nl_langinfo_l(T_FMT_AMPM, locale);
262 const char *time24FormatString = nl_langinfo_l(T_FMT, locale);
264 if (format == VuoTimeFormat_DateTimeShort12)
265 return VuoText_format(
"%s %s", dateFormatString, time12FormatString);
266 else if (format == VuoTimeFormat_DateTimeShort24)
267 return VuoText_format(
"%s %s", dateFormatString, time24FormatString);
268 else if (format == VuoTimeFormat_DateTimeMedium12)
270 else if (format == VuoTimeFormat_DateTimeMedium24)
272 else if (format == VuoTimeFormat_DateTimeLong12)
273 return VuoText_format(
"%%A, %%B %%e, %%Y %s", time12FormatString);
274 else if (format == VuoTimeFormat_DateTimeLong24)
275 return VuoText_format(
"%%A, %%B %%e, %%Y %s", time24FormatString);
276 else if (format == VuoTimeFormat_DateTimeSortable)
277 return strdup(
"%Y-%m-%d %H:%M:%SZ");
278 else if (format == VuoTimeFormat_DateShort)
279 return strdup(dateFormatString);
280 else if (format == VuoTimeFormat_DateMedium)
281 return strdup(
"%b %e, %Y");
282 else if (format == VuoTimeFormat_DateLong)
283 return strdup(
"%A, %B %e, %Y");
284 else if (format == VuoTimeFormat_Time12)
285 return strdup(time12FormatString);
286 else if (format == VuoTimeFormat_Time24)
287 return strdup(time24FormatString);
304 for (
int i = 0; i < numFormats; ++i)
309 bzero(&tm,
sizeof(
struct tm));
311 char *ret = strptime(str, formats[i], &tm);
314 for ( ; *ret != 0 && isspace(*ret); ++ret) {}
322 time_t timeInt = mktime(&tm);
337 const int numFormats = 2;
338 const char *formats[numFormats] = {
339 "%a, %d %b %Y %T %z",
354 const int numFormats = 4;
355 const char *formats[numFormats] = {
356 "%Y-%m-%dT%H:%M:%SZ",
357 "%Y-%m-%d %H:%M:%SZ",
358 "%Y-%m-%dT%H:%M:%S+00:00",
359 "%Y-%m-%d %H:%M:%S+00:00"
370 for (
int i = 0; format[i] != 0; ++i)
371 if (format[i] ==
'Y')
383 CFLocaleRef localeCF = CFLocaleCopyCurrent();
387 locale_t locale = newlocale(LC_ALL_MASK, localeID, NULL);
389 const int numFormats = 15;
390 char *formats[numFormats] = {
412 for (
int i = 0; i < numFormats; ++i)
438 struct tm *tm = localtime(&unixtime);
442 *year = tm->tm_year + 1900;
444 *dayOfYear = tm->tm_yday + 1;
446 *month = tm->tm_mon + 1;
448 *dayOfMonth = tm->tm_mday;
452 strftime(s, 3,
"%V", tm);
456 *dayOfWeek = tm->tm_wday;
460 *minute = tm->tm_min;
464 *second = fmod(time, 60);
466 *second = fmod(60 + fmod(time, 60), 60);
484 bool ret =
VuoTime_getComponents(value, &year, NULL, &month, &dayOfMonth, NULL, &dayOfWeek, &hour, &minute, &second);
488 if (unit == VuoTimeUnit_Millennium)
490 if (roundingMethod == VuoRoundingMethod_Nearest)
491 return VuoTime_make(1000*(year/1000) + (year%1000 > 500 ? 1000 : 0), 1, 1, 0, 0, 0);
492 else if (roundingMethod == VuoRoundingMethod_Down)
494 else if (roundingMethod == VuoRoundingMethod_Up)
495 return VuoTime_make(1000*(year/1000) + (year%1000 + month + dayOfMonth + hour + minute + second > 0 ? 1000 : 0), 1, 1, 0, 0, 0);
497 else if (unit == VuoTimeUnit_Century)
499 if (roundingMethod == VuoRoundingMethod_Nearest)
500 return VuoTime_make(100*(year/100) + (year%100 > 50 ? 100 : 0), 1, 1, 0, 0, 0);
501 else if (roundingMethod == VuoRoundingMethod_Down)
503 else if (roundingMethod == VuoRoundingMethod_Up)
504 return VuoTime_make(100*(year/100) + (year%100 + month + dayOfMonth + hour + minute + second > 0 ? 100 : 0), 1, 1, 0, 0, 0);
506 else if (unit == VuoTimeUnit_Decade)
508 if (roundingMethod == VuoRoundingMethod_Nearest)
509 return VuoTime_make(10*(year/10) + (year%10 > 5 ? 10 : 0), 1, 1, 0, 0, 0);
510 else if (roundingMethod == VuoRoundingMethod_Down)
512 else if (roundingMethod == VuoRoundingMethod_Up)
513 return VuoTime_make(10*(year/10) + (year%10 + month + dayOfMonth + hour + minute + second > 0 ? 10 : 0), 1, 1, 0, 0, 0);
515 else if (unit == VuoTimeUnit_Year)
517 if (roundingMethod == VuoRoundingMethod_Nearest)
518 return VuoTime_make(year + (month > 6 ? 1 : 0), 1, 1, 0, 0, 0);
519 else if (roundingMethod == VuoRoundingMethod_Down)
521 else if (roundingMethod == VuoRoundingMethod_Up)
522 return VuoTime_make(year + (month + dayOfMonth + hour + minute + second > 0 ? 1 : 0), 1, 1, 0, 0, 0);
524 else if (unit == VuoTimeUnit_Quarter)
526 if (roundingMethod == VuoRoundingMethod_Nearest)
527 return VuoTime_make(year, 3*((month-1)/3) + 1 + ((month-1)%3 > 1 ? 3 : 0), 1, 0, 0, 0);
528 else if (roundingMethod == VuoRoundingMethod_Down)
529 return VuoTime_make(year, 3*((month-1)/3) + 1, 1, 0, 0, 0);
530 else if (roundingMethod == VuoRoundingMethod_Up)
531 return VuoTime_make(year, 3*((month-1)/3) + 1 + ((month-1)%3 + dayOfMonth + hour + minute + second > 0 ? 3 : 0), 1, 0, 0, 0);
533 else if (unit == VuoTimeUnit_Month)
535 if (roundingMethod == VuoRoundingMethod_Nearest)
536 return VuoTime_make(year, month + (dayOfMonth > 15 ? 1 : 0), 1, 0, 0, 0);
537 else if (roundingMethod == VuoRoundingMethod_Down)
539 else if (roundingMethod == VuoRoundingMethod_Up)
540 return VuoTime_make(year, month + (dayOfMonth + hour + minute + second > 0 ? 1 : 0), 1, 0, 0, 0);
542 else if (unit == VuoTimeUnit_WeekSunday)
544 if (roundingMethod == VuoRoundingMethod_Nearest)
545 return VuoTime_make(year, month, dayOfMonth + (dayOfWeek > VuoWeekday_Wednesday ? 7-dayOfWeek : -dayOfWeek), 0, 0, 0);
546 else if (roundingMethod == VuoRoundingMethod_Down)
547 return VuoTime_make(year, month, dayOfMonth - dayOfWeek, 0, 0, 0);
548 else if (roundingMethod == VuoRoundingMethod_Up)
549 return VuoTime_make(year, month, dayOfMonth + (dayOfWeek + hour + minute + second > 0 ? 7-dayOfWeek : 0), 0, 0, 0);
551 else if (unit == VuoTimeUnit_WeekMonday)
553 if (dayOfWeek == VuoWeekday_Sunday)
556 if (roundingMethod == VuoRoundingMethod_Nearest)
557 return VuoTime_make(year, month, dayOfMonth + (dayOfWeek > VuoWeekday_Thursday ? 8-dayOfWeek : 1-dayOfWeek), 0, 0, 0);
558 else if (roundingMethod == VuoRoundingMethod_Down)
559 return VuoTime_make(year, month, dayOfMonth - dayOfWeek + 1, 0, 0, 0);
560 else if (roundingMethod == VuoRoundingMethod_Up)
561 return VuoTime_make(year, month, dayOfMonth + (dayOfWeek-1 + hour + minute + second > 0 ? 8-dayOfWeek : 0), 0, 0, 0);
563 else if (unit == VuoTimeUnit_Day)
565 if (roundingMethod == VuoRoundingMethod_Nearest)
566 return VuoTime_make(year, month, dayOfMonth + (hour > 12 ? 1 : 0), 0, 0, 0);
567 else if (roundingMethod == VuoRoundingMethod_Down)
569 else if (roundingMethod == VuoRoundingMethod_Up)
570 return VuoTime_make(year, month, dayOfMonth + (hour + minute + second > 0 ? 1 : 0), 0, 0, 0);
572 else if (unit == VuoTimeUnit_Hour)
574 if (roundingMethod == VuoRoundingMethod_Nearest)
575 return VuoTime_make(year, month, dayOfMonth, hour + (minute > 30 ? 1 : 0), 0, 0);
576 else if (roundingMethod == VuoRoundingMethod_Down)
577 return VuoTime_make(year, month, dayOfMonth, hour, 0, 0);
578 else if (roundingMethod == VuoRoundingMethod_Up)
579 return VuoTime_make(year, month, dayOfMonth, hour + (minute + second > 0 ? 1 : 0), 0, 0);
581 else if (unit == VuoTimeUnit_HalfHour)
583 if (roundingMethod == VuoRoundingMethod_Nearest)
584 return VuoTime_make(year, month, dayOfMonth, hour, 30*(minute/30) + (minute%30 > 15 ? 30 : 0), 0);
585 else if (roundingMethod == VuoRoundingMethod_Down)
586 return VuoTime_make(year, month, dayOfMonth, hour, 30*(minute/30), 0);
587 else if (roundingMethod == VuoRoundingMethod_Up)
588 return VuoTime_make(year, month, dayOfMonth, hour, 30*(minute/30) + (minute%30 + second > 0 ? 30 : 0), 0);
590 else if (unit == VuoTimeUnit_QuarterHour)
592 if (roundingMethod == VuoRoundingMethod_Nearest)
593 return VuoTime_make(year, month, dayOfMonth, hour, 15*(minute/15) + (minute%15 > 7 ? 15 : 0), 0);
594 else if (roundingMethod == VuoRoundingMethod_Down)
595 return VuoTime_make(year, month, dayOfMonth, hour, 15*(minute/15), 0);
596 else if (roundingMethod == VuoRoundingMethod_Up)
597 return VuoTime_make(year, month, dayOfMonth, hour, 15*(minute/15) + (minute%15 + second > 0 ? 15 : 0), 0);
599 else if (unit == VuoTimeUnit_Minute)
601 if (roundingMethod == VuoRoundingMethod_Nearest)
602 return VuoTime_make(year, month, dayOfMonth, hour, minute + (second > 30 ? 1 : 0), 0);
603 else if (roundingMethod == VuoRoundingMethod_Down)
604 return VuoTime_make(year, month, dayOfMonth, hour, minute, 0);
605 else if (roundingMethod == VuoRoundingMethod_Up)
606 return VuoTime_make(year, month, dayOfMonth, hour, minute + (second > 0 ? 1 : 0), 0);
608 else if (unit == VuoTimeUnit_Second)
610 if (roundingMethod == VuoRoundingMethod_Nearest)
611 return lround(value);
612 else if (roundingMethod == VuoRoundingMethod_Down)
614 else if (roundingMethod == VuoRoundingMethod_Up)
630 CFLocaleRef localeCF = CFLocaleCopyCurrent();
639 return formattedTime;
653 locale_t locale = newlocale(LC_ALL_MASK, localeIdentifier, NULL);
654 static dispatch_once_t loggedLocale = 0;
655 dispatch_once(&loggedLocale, ^{
656 VUserLog(
"macOS Locale: %s", localeIdentifier);
657 VUserLog(
" C Locale: %s", querylocale(LC_ALL_MASK, locale));
666 if (format == VuoTimeFormat_DateTimeSortable)
673 char formattedTime[1024];
674 strftime_l(formattedTime, 1024, formatString, tm, locale);