diff options
| author | jan.nijtmans <nijtmans@users.sourceforge.net> | 2024-11-20 21:06:41 (GMT) |
|---|---|---|
| committer | jan.nijtmans <nijtmans@users.sourceforge.net> | 2024-11-20 21:06:41 (GMT) |
| commit | 265092d87f8e25f21787be940c7065d9af187875 (patch) | |
| tree | b112bb72dfd5d4004268a740f46f04398e7c60ee /generic/tclClock.c | |
| parent | 85a7c5fc8407152f15d95e78105b11eef2f99dd6 (diff) | |
| parent | ed6b0e3a8bea5e726283656f7485a681bf68b718 (diff) | |
| download | tcl-265092d87f8e25f21787be940c7065d9af187875.zip tcl-265092d87f8e25f21787be940c7065d9af187875.tar.gz tcl-265092d87f8e25f21787be940c7065d9af187875.tar.bz2 | |
Rebase to 9.0. Improved parsing of leap-seconds
Diffstat (limited to 'generic/tclClock.c')
| -rw-r--r-- | generic/tclClock.c | 39 |
1 files changed, 27 insertions, 12 deletions
diff --git a/generic/tclClock.c b/generic/tclClock.c index 44b0274..c956fd6 100644 --- a/generic/tclClock.c +++ b/generic/tclClock.c @@ -1956,11 +1956,11 @@ ConvertLocalToUTC( /* check DST-hole: if retrieved seconds is out of range */ if (ltzoc->rangesVal[0] > seconds || seconds >= ltzoc->rangesVal[1]) { dstHole: -#if 0 +#if 1 printf("given local-time is outside the time-zone (in DST-hole): " - "%d - offs %d => %d <= %d < %d\n", - (int)fields->localSeconds, fields->tzOffset, - (int)ltzoc->rangesVal[0], (int)seconds, (int)ltzoc->rangesVal[1]); + "%" TCL_LL_MODIFIER "d - offs %d => %" TCL_LL_MODIFIER "d <= %" TCL_LL_MODIFIER "d < %" TCL_LL_MODIFIER "d\n", + fields->localSeconds, fields->tzOffset, + ltzoc->rangesVal[0], seconds, ltzoc->rangesVal[1]); #endif /* because we don't know real TZ (we're outsize), just invalidate local * time (which could be verified in ClockValidDate later) */ @@ -3733,8 +3733,8 @@ ClockScanCommit( } } - /* If seconds overflows the day (no validate and "24:00" case), increase days */ - if (yySecondOfDay >= SECONDS_PER_DAY + ((info->flags & CLF_TIME) && (yyHour == 24))) { + /* If seconds overflows the day (no validate but not "24:00" or leap-second case), increase days */ + if (yySecondOfDay >= SECONDS_PER_DAY + ((info->flags & CLF_TIME) && ((yyHour == 24) || (yySeconds == 60)))) { yydate.julianDay += (yySecondOfDay / SECONDS_PER_DAY); yySecondOfDay %= SECONDS_PER_DAY; } @@ -3785,13 +3785,14 @@ ClockValidDate( const char *errMsg = "", *errCode = ""; TclDateFields temp; int tempCpyFlg = 0; + int leapDay = 1; ClockClientData *dataPtr = opts->dataPtr; #if 0 - printf("yyMonth %d, yyDay %d, yyDayOfYear %d, yyHour %d, yyMinutes %d, yySeconds %d, " - "yySecondOfDay %d, sec %d, daySec %d, tzOffset %d\n", + printf("yyMonth %d, yyDay %d, yyDayOfYear %d, yyHour %d, yyMinutes %d, yySeconds %" TCL_LL_MODIFIER "d, " + "yySecondOfDay %" TCL_LL_MODIFIER "d, sec %" TCL_LL_MODIFIER "d, daySec %" TCL_LL_MODIFIER "d, tzOffset %d\n", yyMonth, yyDay, yydate.dayOfYear, yyHour, yyMinutes, yySeconds, - yySecondOfDay, (int)yydate.localSeconds, (int)(yydate.localSeconds % SECONDS_PER_DAY), + yySecondOfDay, yydate.localSeconds, yydate.localSeconds % SECONDS_PER_DAY, yydate.tzOffset); #endif @@ -3835,6 +3836,12 @@ ClockValidDate( errMsg = "invalid month"; errCode = "month"; goto error; + } else if ((yyMonth == 6) || (yyMonth == 12)) { + /* leap seconds/minutes can be the last day in june or december */ + leapDay = (yyMonth == 12) ? 31: 30; + } else { + /* leap seconds/minutes can be the first day in july or january */ + leapDay = ((yyMonth == 7) || (yyMonth == 1)); } } /* day of month */ @@ -3843,11 +3850,15 @@ ClockValidDate( errMsg = "invalid day"; errCode = "day"; goto error; - } else if ((info->flags & CLF_MONTH)) { + } else if (yyDay != leapDay) { + leapDay = 0; + } + if ((info->flags & CLF_MONTH)) { const int *h = hath[IsGregorianLeapYear(&yydate)]; if (yyDay > h[yyMonth - 1]) { errMsg = "invalid day"; + errCode = "day"; goto error; } } @@ -3882,15 +3893,19 @@ ClockValidDate( errMsg = "invalid time (hour)"; errCode = "hour"; goto error; + } else if (yyHour == 24) { + leapDay = 0; } /* minutes */ - if (yyMinutes < 0 || yyMinutes > 59 || (yyMinutes && (yyHour == 24))) { + if (yyMinutes < 0 || yyMinutes > (leapDay ? 60 : 59) || (yyMinutes && (yyHour == 24))) { errMsg = "invalid time (minutes)"; errCode = "minutes"; goto error; + } else if ((yyMinutes != 29) && (yyMinutes != 59)) { + leapDay = 0; } /* oldscan could return secondOfDay (parsedTime) -1 by invalid time (ex.: 25:00:00) */ - if (yySeconds < 0 || yySeconds > 59 || yySecondOfDay <= -1 || (yySeconds && (yyHour == 24))) { + if (yySeconds < 0 || yySeconds > (leapDay ? 60 : 59) || yySecondOfDay <= -1 || (yySeconds && (yyHour == 24))) { errMsg = "invalid time"; errCode = "seconds"; goto error; |
