avoid TzSpecificLocalTimeToSystemTime

svn: r840
This commit is contained in:
Matthew Flatt 2005-09-12 20:06:56 +00:00
parent 6e6e54d411
commit 7c147ecaec

View File

@ -2035,24 +2035,72 @@ char *scheme_expand_string_filename(Scheme_Object *o, const char *errorin, int *
# define GET_FF_NAME(fd) fd.cFileName
static time_t convert_date(const FILETIME *ft)
{
LONGLONG l;
LONGLONG l, delta;
FILETIME ft2;
SYSTEMTIME st, st2;
SYSTEMTIME st;
TIME_ZONE_INFORMATION tz;
/* FindFirstFile incorrectly shifts for daylight saving. Counteract
the difference by using FileTimeToLocalFileTime, which also
shifts incorrectly. There's a race condition here, because we
might cross the daylight-saving boundary between the time that
FindFirstFile runs and FileTimeToLocalFileTime runs. Cross your
fingers... */
/* FindFirstFile incorrectly shifts for daylight saving. It
subtracts an hour to get to UTC when daylight saving is in effect
now, even when daylight saving was not in effect when the file
was saved. Counteract the difference. There's a race condition
here, because we might cross the daylight-saving boundary between
the time that FindFirstFile runs and GetTimeZoneInformation
runs. Cross your fingers... */
FileTimeToLocalFileTime(ft, &ft2);
FileTimeToSystemTime(&ft2, &st);
TzSpecificLocalTimeToSystemTime(NULL, &st, &st2);
SystemTimeToFileTime(&st2, &ft2);
delta = 0;
if (GetTimeZoneInformation(&tz) == TIME_ZONE_ID_DAYLIGHT) {
/* Daylight saving is in effect now, so there may be a bad
shift. Check the file's date. */
int start_day_of_month, end_day_of_month, first_day_of_week, diff, end_shift;
l = ((((LONGLONG)ft2.dwHighDateTime << 32) | ft2.dwLowDateTime)
/* Valid only when the months match: */
first_day_of_week = (st.wDayOfWeek - (st.wDay - 1 - (((st.wDay - 1) / 7) * 7)));
if (first_day_of_week < 0)
first_day_of_week += 7;
diff = (tz.DaylightDate.wDayOfWeek - first_day_of_week);
if (diff < 0)
diff += 7;
start_day_of_month = 1 + (((tz.DaylightDate.wDay - 1) * 7)
+ diff);
diff = (tz.StandardDate.wDayOfWeek - first_day_of_week);
if (diff < 0)
diff += 7;
end_day_of_month = 1 + (((tz.StandardDate.wDay - 1) * 7)
+ diff);
/* Count ambigious range (when the clock goes back) as
in standard time. We assume that subtracting the
ambiguous range does not go back into the previous day,
and that the shift is a multiple of an hour. */
end_shift = ((tz.StandardBias - tz.DaylightBias) / 60);
if ((st.wMonth < tz.DaylightDate.wMonth)
|| ((st.wMonth == tz.DaylightDate.wMonth)
&& ((st.wDay < start_day_of_month)
|| ((st.wDay == start_day_of_month)
&& (st.wHour < tz.DaylightDate.wHour))))) {
/* Daylight saving had not yet started. */
delta = ((tz.StandardBias - tz.DaylightBias) * 60);
} else if ((st.wMonth > tz.StandardDate.wMonth)
|| ((st.wMonth == tz.StandardDate.wMonth)
&& ((st.wDay > end_day_of_month)
|| ((st.wDay == end_day_of_month)
&& (st.wHour >= (tz.StandardDate.wHour
- end_shift)))))) {
/* Daylight saving was already over. */
delta = ((tz.StandardBias - tz.DaylightBias) * 60);
}
}
l = ((((LONGLONG)ft->dwHighDateTime << 32) | ft->dwLowDateTime)
- (((LONGLONG)0x019DB1DE << 32) | 0xD53E8000));
l /= 10000000;
l += delta;
return (time_t)l;
}