Are there any present-day systems with unsigned 64-bit time_t's?
Nothing major that I know of. However, NewOS does it that way and might be considered to be present-day.
That being true, I've attached a change that caters to 64-bit unsigned systems (with the usual mangled copy below); these changes are relative to the current ftpable version of localtime.c --ado 8.17 2110 lines 8.19 2126 lines *** /tmp/,alocaltime.c 2012-07-11 15:55:34.439147200 -0400 --- /tmp/,blocaltime.c 2012-07-11 15:55:34.641947500 -0400 *************** *** 5,11 **** #ifndef lint #ifndef NOID ! static char elsieid[] = "@(#)localtime.c 8.17"; #endif /* !defined NOID */ #endif /* !defined lint */ --- 5,11 ---- #ifndef lint #ifndef NOID ! static char elsieid[] = "@(#)localtime.c 8.19"; #endif /* !defined NOID */ #endif /* !defined lint */ *************** *** 277,282 **** --- 277,287 ---- /* ** And to get the latest zone names into tzname. . . */ + for (i = 0; i < sp->typecnt; ++i) { + register const struct ttinfo * const ttisp = &sp->ttis[i]; + + tzname[ttisp->tt_isdst] = &sp->chars[ttisp->tt_abbrind]; + } for (i = 0; i < sp->timecnt; ++i) { register const struct ttinfo * const ttisp = &sp->ttis[ *************** *** 489,508 **** ** signed time_t system but using a data file with ** unsigned values (or vice versa). */ ! for (i = 0; i < sp->timecnt - 2; ++i) ! if (sp->ats[i] > sp->ats[i + 1]) { ! ++i; if (TYPE_SIGNED(time_t)) { /* ** Ignore the end (easy). */ ! sp->timecnt = i; } else { /* ** Ignore the beginning (harder). */ register int j; for (j = 0; j + i < sp->timecnt; ++j) { sp->ats[j] = sp->ats[j + i]; sp->types[j] = sp->types[j + i]; --- 494,524 ---- ** signed time_t system but using a data file with ** unsigned values (or vice versa). */ ! for (i = 0; i < sp->timecnt; ++i) ! if ((i < sp->timecnt - 1 && ! sp->ats[i] > sp->ats[i + 1]) || ! (i == sp->timecnt - 1 && !TYPE_SIGNED(time_t) && ! sp->ats[i] > ! ((stored == 4) ? INT32_MAX : INT64_MAX))) { if (TYPE_SIGNED(time_t)) { /* ** Ignore the end (easy). */ ! sp->timecnt = i + 1; } else { /* ** Ignore the beginning (harder). */ register int j; + /* + ** Keep the record right before the + ** epoch boundary, + ** but tweak it so that it starts + ** right with the epoch + ** (thanks to Doug Bailey). + */ + sp->ats[i] = 0; for (j = 0; j + i < sp->timecnt; ++j) { sp->ats[j] = sp->ats[j + i]; sp->types[j] = sp->types[j + i];