localtime.c (1365bb722af1365baee6ea1e3d44917533908d53) | localtime.c (a979394afeb5c20fc58c5f5b005d51eb8f92f666) |
---|---|
1/* Convert timestamp from time_t to struct tm. */ 2 3/* 4** This file is in the public domain, so clarified as of 5** 1996-06-05 by Arthur David Olson. 6*/ 7 8/* --- 111 unchanged lines hidden (view full) --- 120static char const UNSPEC[] = "-00"; 121 122/* How many extra bytes are needed at the end of struct state's chars array. 123 This needs to be at least 1 for null termination in case the input 124 data isn't properly terminated, and it also needs to be big enough 125 for ttunspecified to work without crashing. */ 126enum { CHARS_EXTRA = max(sizeof UNSPEC, 2) - 1 }; 127 | 1/* Convert timestamp from time_t to struct tm. */ 2 3/* 4** This file is in the public domain, so clarified as of 5** 1996-06-05 by Arthur David Olson. 6*/ 7 8/* --- 111 unchanged lines hidden (view full) --- 120static char const UNSPEC[] = "-00"; 121 122/* How many extra bytes are needed at the end of struct state's chars array. 123 This needs to be at least 1 for null termination in case the input 124 data isn't properly terminated, and it also needs to be big enough 125 for ttunspecified to work without crashing. */ 126enum { CHARS_EXTRA = max(sizeof UNSPEC, 2) - 1 }; 127 |
128/* Limit to time zone abbreviation length in POSIX.1-2017-style TZ strings. | 128/* Limit to time zone abbreviation length in proleptic TZ strings. |
129 This is distinct from TZ_MAX_CHARS, which limits TZif file contents. */ 130#ifndef TZNAME_MAXIMUM 131# define TZNAME_MAXIMUM 255 132#endif 133 134/* A representation of the contents of a TZif file. Ideally this 135 would have no size limits; the following sizes should suffice for 136 practical use. This struct should not be too large, as instances --- 7 unchanged lines hidden (view full) --- 144 bool goback; 145 bool goahead; 146 time_t ats[TZ_MAX_TIMES]; 147 unsigned char types[TZ_MAX_TIMES]; 148 struct ttinfo ttis[TZ_MAX_TYPES]; 149 char chars[max(max(TZ_MAX_CHARS + CHARS_EXTRA, sizeof "UTC"), 150 2 * (TZNAME_MAXIMUM + 1))]; 151 struct lsinfo lsis[TZ_MAX_LEAPS]; | 129 This is distinct from TZ_MAX_CHARS, which limits TZif file contents. */ 130#ifndef TZNAME_MAXIMUM 131# define TZNAME_MAXIMUM 255 132#endif 133 134/* A representation of the contents of a TZif file. Ideally this 135 would have no size limits; the following sizes should suffice for 136 practical use. This struct should not be too large, as instances --- 7 unchanged lines hidden (view full) --- 144 bool goback; 145 bool goahead; 146 time_t ats[TZ_MAX_TIMES]; 147 unsigned char types[TZ_MAX_TIMES]; 148 struct ttinfo ttis[TZ_MAX_TYPES]; 149 char chars[max(max(TZ_MAX_CHARS + CHARS_EXTRA, sizeof "UTC"), 150 2 * (TZNAME_MAXIMUM + 1))]; 151 struct lsinfo lsis[TZ_MAX_LEAPS]; |
152 153 /* The time type to use for early times or if no transitions. 154 It is always zero for recent tzdb releases. 155 It might be nonzero for data from tzdb 2018e or earlier. */ 156 int defaulttype; | |
157}; 158 159enum r_type { 160 JULIAN_DAY, /* Jn = Julian day */ 161 DAY_OF_YEAR, /* n = day of year */ 162 MONTH_NTH_DAY_OF_WEEK /* Mm.n.d = month, week, day of week */ 163}; 164 --- 47 unchanged lines hidden (view full) --- 212 213/* 214** Section 4.12.3 of X3.159-1989 requires that 215** Except for the strftime function, these functions [asctime, 216** ctime, gmtime, localtime] return values in one of two static 217** objects: a broken-down time structure and an array of char. 218** Thanks to Paul Eggert for noting this. 219** | 152}; 153 154enum r_type { 155 JULIAN_DAY, /* Jn = Julian day */ 156 DAY_OF_YEAR, /* n = day of year */ 157 MONTH_NTH_DAY_OF_WEEK /* Mm.n.d = month, week, day of week */ 158}; 159 --- 47 unchanged lines hidden (view full) --- 207 208/* 209** Section 4.12.3 of X3.159-1989 requires that 210** Except for the strftime function, these functions [asctime, 211** ctime, gmtime, localtime] return values in one of two static 212** objects: a broken-down time structure and an array of char. 213** Thanks to Paul Eggert for noting this. 214** |
220** This requirement was removed in C99, so support it only if requested, 221** as support is more likely to lead to bugs in badly written programs. | 215** Although this requirement was removed in C99 it is still present in POSIX. 216** Follow the requirement if SUPPORT_C89, even though this is more likely to 217** trigger latent bugs in programs. |
222*/ 223 224#if SUPPORT_C89 225static struct tm tm; 226#endif 227 228#if 2 <= HAVE_TZNAME + TZ_TIME_T 229char * tzname[2] = { --- 538 unchanged lines hidden (view full) --- 768 for (i = 0; i < ts->typecnt; i++) 769 sp->ttis[sp->typecnt++] = ts->ttis[i]; 770 } 771 } 772 } 773 if (sp->typecnt == 0) 774 return EINVAL; 775 | 218*/ 219 220#if SUPPORT_C89 221static struct tm tm; 222#endif 223 224#if 2 <= HAVE_TZNAME + TZ_TIME_T 225char * tzname[2] = { --- 538 unchanged lines hidden (view full) --- 764 for (i = 0; i < ts->typecnt; i++) 765 sp->ttis[sp->typecnt++] = ts->ttis[i]; 766 } 767 } 768 } 769 if (sp->typecnt == 0) 770 return EINVAL; 771 |
776 /* Infer sp->defaulttype from the data. Although this default 777 type is always zero for data from recent tzdb releases, 778 things are trickier for data from tzdb 2018e or earlier. 779 780 The first set of heuristics work around bugs in 32-bit data 781 generated by tzdb 2013c or earlier. The workaround is for 782 zones like Australia/Macquarie where timestamps before the 783 first transition have a time type that is not the earliest 784 standard-time type. See: 785 https://mm.icann.org/pipermail/tz/2013-May/019368.html */ 786 /* 787 ** If type 0 does not specify local time, or is unused in transitions, 788 ** it's the type to use for early times. 789 */ 790 for (i = 0; i < sp->timecnt; ++i) 791 if (sp->types[i] == 0) 792 break; 793 i = i < sp->timecnt && ! ttunspecified(sp, 0) ? -1 : 0; 794 /* 795 ** Absent the above, 796 ** if there are transition times 797 ** and the first transition is to a daylight time 798 ** find the standard type less than and closest to 799 ** the type of the first transition. 800 */ 801 if (i < 0 && sp->timecnt > 0 && sp->ttis[sp->types[0]].tt_isdst) { 802 i = sp->types[0]; 803 while (--i >= 0) 804 if (!sp->ttis[i].tt_isdst) 805 break; 806 } 807 /* The next heuristics are for data generated by tzdb 2018e or 808 earlier, for zones like EST5EDT where the first transition 809 is to DST. */ 810 /* 811 ** If no result yet, find the first standard type. 812 ** If there is none, punt to type zero. 813 */ 814 if (i < 0) { 815 i = 0; 816 while (sp->ttis[i].tt_isdst) 817 if (++i >= sp->typecnt) { 818 i = 0; 819 break; 820 } 821 } 822 /* A simple 'sp->defaulttype = 0;' would suffice here if we 823 didn't have to worry about 2018e-or-earlier data. Even 824 simpler would be to remove the defaulttype member and just 825 use 0 in its place. */ 826 sp->defaulttype = i; 827 | |
828 return 0; 829} 830 831/* Load tz data from the file named NAME into *SP. Read extended 832 format if DOEXTEND. Return 0 on success, an errno value on failure. */ 833static int 834tzload(char const *name, struct state *sp, bool doextend) 835{ --- 29 unchanged lines hidden (view full) --- 865} 866 867/* 868** Given a pointer into a timezone string, scan until a character that is not 869** a valid character in a time zone abbreviation is found. 870** Return a pointer to that character. 871*/ 872 | 772 return 0; 773} 774 775/* Load tz data from the file named NAME into *SP. Read extended 776 format if DOEXTEND. Return 0 on success, an errno value on failure. */ 777static int 778tzload(char const *name, struct state *sp, bool doextend) 779{ --- 29 unchanged lines hidden (view full) --- 809} 810 811/* 812** Given a pointer into a timezone string, scan until a character that is not 813** a valid character in a time zone abbreviation is found. 814** Return a pointer to that character. 815*/ 816 |
873ATTRIBUTE_REPRODUCIBLE static const char * | 817ATTRIBUTE_PURE_114833 static const char * |
874getzname(register const char *strp) 875{ 876 register char c; 877 878 while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' && 879 c != '+') 880 ++strp; 881 return strp; --- 4 unchanged lines hidden (view full) --- 886** delimiter of the time zone abbreviation is located. 887** Return a pointer to the delimiter. 888** 889** As with getzname above, the legal character set is actually quite 890** restricted, with other characters producing undefined results. 891** We don't do any checking here; checking is done later in common-case code. 892*/ 893 | 818getzname(register const char *strp) 819{ 820 register char c; 821 822 while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' && 823 c != '+') 824 ++strp; 825 return strp; --- 4 unchanged lines hidden (view full) --- 830** delimiter of the time zone abbreviation is located. 831** Return a pointer to the delimiter. 832** 833** As with getzname above, the legal character set is actually quite 834** restricted, with other characters producing undefined results. 835** We don't do any checking here; checking is done later in common-case code. 836*/ 837 |
894ATTRIBUTE_REPRODUCIBLE static const char * | 838ATTRIBUTE_PURE_114833 static const char * |
895getqzname(register const char *strp, const int delim) 896{ 897 register int c; 898 899 while ((c = *strp) != '\0' && c != delim) 900 ++strp; 901 return strp; 902} --- 235 unchanged lines hidden (view full) --- 1138 ** question. To get the year-relative time of the specified local 1139 ** time on that day, add the transition time and the current offset 1140 ** from UT. 1141 */ 1142 return value + rulep->r_time + offset; 1143} 1144 1145/* | 839getqzname(register const char *strp, const int delim) 840{ 841 register int c; 842 843 while ((c = *strp) != '\0' && c != delim) 844 ++strp; 845 return strp; 846} --- 235 unchanged lines hidden (view full) --- 1082 ** question. To get the year-relative time of the specified local 1083 ** time on that day, add the transition time and the current offset 1084 ** from UT. 1085 */ 1086 return value + rulep->r_time + offset; 1087} 1088 1089/* |
1146** Given a POSIX.1-2017-style TZ string, fill in the rule tables as | 1090** Given a POSIX.1 proleptic TZ string, fill in the rule tables as |
1147** appropriate. 1148*/ 1149 1150static bool 1151tzparse(const char *name, struct state *sp, struct state const *basep) 1152{ 1153 const char * stdname; 1154 const char * dstname; --- 218 unchanged lines hidden (view full) --- 1373 ** the daylight saving time offset to 1374 ** the transition time; otherwise, add 1375 ** the standard time offset to the 1376 ** transition time. 1377 */ 1378 /* 1379 ** Transitions from DST to DDST 1380 ** will effectively disappear since | 1091** appropriate. 1092*/ 1093 1094static bool 1095tzparse(const char *name, struct state *sp, struct state const *basep) 1096{ 1097 const char * stdname; 1098 const char * dstname; --- 218 unchanged lines hidden (view full) --- 1317 ** the daylight saving time offset to 1318 ** the transition time; otherwise, add 1319 ** the standard time offset to the 1320 ** transition time. 1321 */ 1322 /* 1323 ** Transitions from DST to DDST 1324 ** will effectively disappear since |
1381 ** POSIX.1-2017 provides for only one | 1325 ** proleptic TZ strings have only one |
1382 ** DST offset. 1383 */ 1384 if (isdst && !sp->ttis[j].tt_ttisstd) { 1385 sp->ats[i] += dstoffset - 1386 theirdstoffset; 1387 } else { 1388 sp->ats[i] += stdoffset - 1389 theirstdoffset; --- 12 unchanged lines hidden (view full) --- 1402 sp->typecnt = 2; 1403 } 1404 } else { 1405 dstlen = 0; 1406 sp->typecnt = 1; /* only standard time */ 1407 sp->timecnt = 0; 1408 init_ttinfo(&sp->ttis[0], -stdoffset, false, 0); 1409 } | 1326 ** DST offset. 1327 */ 1328 if (isdst && !sp->ttis[j].tt_ttisstd) { 1329 sp->ats[i] += dstoffset - 1330 theirdstoffset; 1331 } else { 1332 sp->ats[i] += stdoffset - 1333 theirstdoffset; --- 12 unchanged lines hidden (view full) --- 1346 sp->typecnt = 2; 1347 } 1348 } else { 1349 dstlen = 0; 1350 sp->typecnt = 1; /* only standard time */ 1351 sp->timecnt = 0; 1352 init_ttinfo(&sp->ttis[0], -stdoffset, false, 0); 1353 } |
1410 sp->defaulttype = 0; | |
1411 sp->charcnt = charcnt; 1412 cp = sp->chars; 1413 memcpy(cp, stdname, stdlen); 1414 cp += stdlen; 1415 *cp++ = '\0'; 1416 if (dstlen != 0) { 1417 memcpy(cp, dstname, dstlen); 1418 *(cp + dstlen) = '\0'; --- 50 unchanged lines hidden (view full) --- 1469 */ 1470 sp->leapcnt = 0; /* so, we're off a little */ 1471 sp->timecnt = 0; 1472 sp->typecnt = 0; 1473 sp->charcnt = 0; 1474 sp->goback = sp->goahead = false; 1475 init_ttinfo(&sp->ttis[0], 0, false, 0); 1476 strcpy(sp->chars, utc); | 1354 sp->charcnt = charcnt; 1355 cp = sp->chars; 1356 memcpy(cp, stdname, stdlen); 1357 cp += stdlen; 1358 *cp++ = '\0'; 1359 if (dstlen != 0) { 1360 memcpy(cp, dstname, dstlen); 1361 *(cp + dstlen) = '\0'; --- 50 unchanged lines hidden (view full) --- 1412 */ 1413 sp->leapcnt = 0; /* so, we're off a little */ 1414 sp->timecnt = 0; 1415 sp->typecnt = 0; 1416 sp->charcnt = 0; 1417 sp->goback = sp->goahead = false; 1418 init_ttinfo(&sp->ttis[0], 0, false, 0); 1419 strcpy(sp->chars, utc); |
1477 sp->defaulttype = 0; | |
1478 return 0; 1479 } else { 1480 int err = tzload(name, sp, true); 1481 if (err != 0 && name && name[0] != ':' && tzparse(name, sp, NULL)) 1482 err = 0; 1483 if (err == 0) 1484 err = scrub_abbrs(sp); 1485 return err; --- 88 unchanged lines hidden (view full) --- 1574 1575void 1576tzfree(timezone_t sp) 1577{ 1578 free(sp); 1579} 1580 1581/* | 1420 return 0; 1421 } else { 1422 int err = tzload(name, sp, true); 1423 if (err != 0 && name && name[0] != ':' && tzparse(name, sp, NULL)) 1424 err = 0; 1425 if (err == 0) 1426 err = scrub_abbrs(sp); 1427 return err; --- 88 unchanged lines hidden (view full) --- 1516 1517void 1518tzfree(timezone_t sp) 1519{ 1520 free(sp); 1521} 1522 1523/* |
1582** NetBSD 6.1.4 has ctime_rz, but omit it because POSIX says ctime and 1583** ctime_r are obsolescent and have potential security problems that | 1524** NetBSD 6.1.4 has ctime_rz, but omit it because C23 deprecates ctime and 1525** POSIX.1-2024 removes ctime_r. Both have potential security problems that |
1584** ctime_rz would share. Callers can instead use localtime_rz + strftime. 1585** 1586** NetBSD 6.1.4 has tzgetname, but omit it because it doesn't work 1587** in zones with three or more time zone abbreviations. 1588** Callers can instead use localtime_rz + strftime. 1589*/ 1590 1591#endif 1592 1593/* 1594** The easy way to behave "as if no library function calls" localtime 1595** is to not call it, so we drop its guts into "localsub", which can be 1596** freely called. (And no, the PANS doesn't require the above behavior, 1597** but it *is* desirable.) 1598** 1599** If successful and SETNAME is nonzero, 1600** set the applicable parts of tzname, timezone and altzone; | 1526** ctime_rz would share. Callers can instead use localtime_rz + strftime. 1527** 1528** NetBSD 6.1.4 has tzgetname, but omit it because it doesn't work 1529** in zones with three or more time zone abbreviations. 1530** Callers can instead use localtime_rz + strftime. 1531*/ 1532 1533#endif 1534 1535/* 1536** The easy way to behave "as if no library function calls" localtime 1537** is to not call it, so we drop its guts into "localsub", which can be 1538** freely called. (And no, the PANS doesn't require the above behavior, 1539** but it *is* desirable.) 1540** 1541** If successful and SETNAME is nonzero, 1542** set the applicable parts of tzname, timezone and altzone; |
1601** however, it's OK to omit this step 1602** if the timezone is compatible with POSIX.1-2017 | 1543** however, it's OK to omit this step for proleptic TZ strings |
1603** since in that case tzset should have already done this step correctly. 1604** SETNAME's type is int_fast32_t for compatibility with gmtsub, 1605** but it is actually a boolean and its value should be 0 or 1. 1606*/ 1607 1608/*ARGSUSED*/ 1609static struct tm * 1610localsub(struct state const *sp, time_t const *timep, int_fast32_t setname, --- 51 unchanged lines hidden (view full) --- 1662 if (! (INT_MIN <= newy && newy <= INT_MAX)) 1663 return NULL; 1664 result->tm_year = newy; 1665#endif 1666 } 1667 return result; 1668 } 1669 if (sp->timecnt == 0 || t < sp->ats[0]) { | 1544** since in that case tzset should have already done this step correctly. 1545** SETNAME's type is int_fast32_t for compatibility with gmtsub, 1546** but it is actually a boolean and its value should be 0 or 1. 1547*/ 1548 1549/*ARGSUSED*/ 1550static struct tm * 1551localsub(struct state const *sp, time_t const *timep, int_fast32_t setname, --- 51 unchanged lines hidden (view full) --- 1603 if (! (INT_MIN <= newy && newy <= INT_MAX)) 1604 return NULL; 1605 result->tm_year = newy; 1606#endif 1607 } 1608 return result; 1609 } 1610 if (sp->timecnt == 0 || t < sp->ats[0]) { |
1670 i = sp->defaulttype; | 1611 i = 0; |
1671 } else { 1672 register int lo = 1; 1673 register int hi = sp->timecnt; 1674 1675 while (lo < hi) { 1676 register int mid = (lo + hi) >> 1; 1677 1678 if (t < sp->ats[mid]) --- 798 unchanged lines hidden (view full) --- 2477 } 2478 tzset_unlocked(); 2479 t = mktime_tzname(lclptr, tmp, true); 2480 unlock(); 2481 return t; 2482} 2483 2484#if STD_INSPIRED | 1612 } else { 1613 register int lo = 1; 1614 register int hi = sp->timecnt; 1615 1616 while (lo < hi) { 1617 register int mid = (lo + hi) >> 1; 1618 1619 if (t < sp->ats[mid]) --- 798 unchanged lines hidden (view full) --- 2418 } 2419 tzset_unlocked(); 2420 t = mktime_tzname(lclptr, tmp, true); 2421 unlock(); 2422 return t; 2423} 2424 2425#if STD_INSPIRED |
2485/* This function is obsolescent and may disapper in future releases. | 2426/* This function is obsolescent and may disappear in future releases. |
2486 Callers can instead use mktime. */ 2487time_t 2488timelocal(struct tm *tmp) 2489{ 2490 if (tmp != NULL) 2491 tmp->tm_isdst = -1; /* in case it wasn't initialized */ 2492 return mktime(tmp); 2493} 2494#endif 2495 2496#ifndef EXTERN_TIMEOFF 2497# ifndef timeoff 2498# define timeoff my_timeoff /* Don't collide with OpenBSD 7.4 <time.h>. */ 2499# endif 2500# define EXTERN_TIMEOFF static 2501#endif 2502 | 2427 Callers can instead use mktime. */ 2428time_t 2429timelocal(struct tm *tmp) 2430{ 2431 if (tmp != NULL) 2432 tmp->tm_isdst = -1; /* in case it wasn't initialized */ 2433 return mktime(tmp); 2434} 2435#endif 2436 2437#ifndef EXTERN_TIMEOFF 2438# ifndef timeoff 2439# define timeoff my_timeoff /* Don't collide with OpenBSD 7.4 <time.h>. */ 2440# endif 2441# define EXTERN_TIMEOFF static 2442#endif 2443 |
2503/* This function is obsolescent and may disapper in future releases. | 2444/* This function is obsolescent and may disappear in future releases. |
2504 Callers can instead use mktime_z with a fixed-offset zone. */ 2505EXTERN_TIMEOFF time_t 2506timeoff(struct tm *tmp, long offset) 2507{ 2508 if (tmp) 2509 tmp->tm_isdst = 0; 2510 _once(&gmt_once, gmtcheck); 2511 return time1(tmp, gmtsub, gmtptr, offset); --- 164 unchanged lines hidden --- | 2445 Callers can instead use mktime_z with a fixed-offset zone. */ 2446EXTERN_TIMEOFF time_t 2447timeoff(struct tm *tmp, long offset) 2448{ 2449 if (tmp) 2450 tmp->tm_isdst = 0; 2451 _once(&gmt_once, gmtcheck); 2452 return time1(tmp, gmtsub, gmtptr, offset); --- 164 unchanged lines hidden --- |