38 y -= (m <= 2) ? 1 : 0;
40 const int64_t era = ((y >= 0) ? y : (y - 399)) / 400;
41 const int64_t yoe =
static_cast<int64_t
>(y) - (era * 400);
42 const int64_t doy = (((153 * (m + ((m > 2) ? -3 : 9))) + 2) / 5)
44 const int64_t doe = (yoe * 365) + (yoe / 4) - (yoe / 100) + doy;
46 return (era * 146097) + doe - 719468;
66static bool fields_sane(
int year,
int mon,
int day,
int hour,
int min,
int sec)
68 return ((year >= 1970) && (year <= 9999) &&
69 (mon >= 1) && (mon <= 12) &&
70 (day >= 1) && (day <= 31) &&
71 (hour >= 0) && (hour <= 23) &&
72 (min >= 0) && (min <= 59) &&
73 (sec >= 0) && (sec <= 60));
80int64_t
civil_to_epoch(
int year,
int mon,
int day,
int hour,
int min,
int sec)
84 return (days * 86400) + (
static_cast<int64_t
>(hour) * 3600) +
85 (
static_cast<int64_t
>(min) * 60) + sec;
90 static const char *
const MONTHS =
"JanFebMarAprMayJunJulAugSepOctNovDec";
97 for (i = 0; i < 12; i++) {
98 if (memcmp(mmm, MONTHS + (i * 3), 3U) == 0) {
108 char mon_abbrev[4] = { 0 };
116 if ((date == NULL) || (time_str == NULL) || (out == NULL)) {
122 if (sscanf(date,
"%3s %d %d", mon_abbrev, &day, &year) != 3) {
125 if (sscanf(time_str,
"%d:%d:%d", &hour, &min, &sec) != 3) {
130 if ((mon == 0) || !
fields_sane(year, mon, day, hour, min, sec)) {
140 char mon_abbrev[4] = { 0 };
141 char zone[8] = { 0 };
149 if ((hdr == NULL) || (out == NULL)) {
156 if (sscanf(hdr,
"%*3s, %2d %3s %4d %2d:%2d:%2d %7s",
157 &day, mon_abbrev, &year, &hour, &min, &sec, zone) != 7) {
160 if (strcmp(zone,
"GMT") != 0) {
165 if ((mon == 0) || !
fields_sane(year, mon, day, hour, min, sec)) {
176 const int64_t w = (days + 4) % 7;
177 return (w < 0) ? (w + 7) : w;
184 return d1 + ((7 -
weekday(d1)) % 7) + (7 * (n - 1));
198 const int64_t std_s = utc + (
static_cast<int64_t
>(std_off_min) * 60);
199 const int64_t day = (std_s >= 0) ? (std_s / 86400) : (((std_s + 1) / 86400) - 1);
200 int y = 1970 +
static_cast<int>((day * 400) / 146097);
206 const int64_t loc = (2 * 3600) - (
static_cast<int64_t
>(std_off_min) * 60);
216 off = (
nth_sunday(y, 11, 1) * 86400) + loc - 3600;
229 const bool dst = (on < off) ? ((utc >= on) && (utc < off))
230 : ((utc >= on) || (utc < off));
231 return std_off_min + (dst ? 60 : 0);
bool civil_parse_http_date(const char *hdr, int64_t *out)
Parse an HTTP-date in IMF-fixdate form into an epoch value.
int civil_month_from_abbrev(const char *mmm)
Map a three-letter English month abbreviation to 1–12.
bool civil_parse_build_stamp(const char *date, const char *time_str, int64_t *out)
Parse the compiler's DATE / TIME pair into an epoch value.
int64_t civil_to_epoch(int year, int mon, int day, int hour, int min, int sec)
Convert a UTC civil date/time to seconds since the Unix epoch.
static int64_t nth_sunday(int y, int m, int n)
Day count of the n th Sunday of a month (n >= 1).
static bool fields_sane(int year, int mon, int day, int hour, int min, int sec)
Range-check a parsed civil date/time.
static int64_t days_from_civil(int y, int m, int d)
Days from 1970-01-01 to the given proleptic-Gregorian civil date.
static int64_t weekday(int64_t days)
Day of week of a day count from days_from_civil(), 0 = Sunday.
int civil_local_offset_min(int64_t utc, int std_off_min, int rule)
Offset from UTC in force at utc, DST included.
static int64_t last_sunday(int y, int m)
Day count of the last Sunday of a month (m <= 11).
TZ-independent calendar arithmetic and date-string parsing.