/**************************************************************************** * * Open Watcom Project * * Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved. * * ======================================================================== * * This file contains Original Code and/or Modifications of Original * Code as defined in and that are subject to the Sybase Open Watcom * Public License version 1.0 (the 'License'). You may not use this file * except in compliance with the License. BY USING THIS FILE YOU AGREE TO * ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is * provided with the Original Code and Modifications, and is also * available at www.sybase.com/developer/opensource. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR * NON-INFRINGEMENT. Please see the License for the specific language * governing rights and limitations under the License. * * ======================================================================== * * Description: __brktime() is an internal function to convert time to struct tm * ****************************************************************************/ #include "variety.h" #include <time.h> #include "thetime.h" #include "timedata.h" // #define DAYS_IN_4_YRS ( 365 + 365 + 365 + 366 ) // #define DAYS_IN_400_YRS ( ( 100 * DAYS_IN_4_YRS ) - 3 ) // #define SECONDS_PER_DAY ( 24 * 60 * 60 ) // extern short __diyr[], __dilyr[]; /* The number of leap years from year 1 to year 1900 is 460. The number of leap years from year 1 to current year is expressed by "years/4 - years/100 + years/400". To determine the number of leap years from current year to 1900, we subtract 460 from the formula result. We do this since "days" is the number of days since 1900. */ static unsigned long __DaysToJan1( unsigned year ) { unsigned years = 1900 + year - 1; unsigned leap_days = years / 4 - years / 100 + years / 400 - 460; return( year * 365UL + leap_days ); } /* __brktime breaks down a calendar time (clock) into a struct tm t */ struct tm *__brktime( unsigned long days, time_t wallclock, long gmtdelta, // localtime - gmtime struct tm *t ) { unsigned long secs; unsigned year; int day_of_year; int month; short const *month_start; /* If date is Jan 1, 1970 0:00 to 12:00 UTC and we are west of UTC then add a day to wallclock, subtract the gmtdelta value, and decrement the calculated days. This prevents local times such as "Wed Dec 31 19:00:00 1969 (EST)" from being erroneously reported as "Sun Feb 6 01:28:16 2106 (EST)" since (wallclock - gmtdelta) wraps (i.e., wallclock < gmtdelta). */ if( wallclock < 12 * 60 * 60UL && gmtdelta > 0 ) wallclock += SECONDS_PER_DAY, days--; /* days compensated for wallclock one day ahead */ wallclock -= ( time_t ) gmtdelta; days += wallclock / SECONDS_PER_DAY; secs = wallclock % SECONDS_PER_DAY; t->tm_hour = ( int ) ( secs / 3600 ) ; secs = secs % 3600; t->tm_min = ( int ) ( secs / 60 ); t->tm_sec = secs % 60; // The following two lines are not needed in the current implementation // because the range of values for days does not exceed DAYS_IN_400_YRS. // Even if it did, the algorithm still computes the correct values. // // unsigned year400s; // // year400s = (days / DAYS_IN_400_YRS) * 400; // days %= DAYS_IN_400_YRS; // // It is OK to reduce days to a value less than DAYS_IN_400_YRS, because // DAYS_IN_400_YRS is exactly divisible by 7. If it wasn't divisible by 7, // then the following line which appears at the bottom, should be computed // before the value of days is range reduced. // t->tm_wday = (days + 1) % 7; /* 24-sep-92 */ // year = days / 365; day_of_year = ( int ) ( days - __DaysToJan1( year ) ); while( day_of_year < 0 ) { --year; day_of_year += __leapyear( year + 1900 ) + 365; } // year += year400s; t->tm_yday = day_of_year; t->tm_year = ( int ) year; month_start = __diyr; if( __leapyear( year + 1900 ) ) month_start = __dilyr; month = day_of_year / 31; /* approximate month */ if( day_of_year >= month_start[month + 1] ) ++month; t->tm_mon = month; t->tm_mday = day_of_year - month_start[month] + 1; /* Calculate the day of the week */ /* Jan 1,1900 is a Monday */ t->tm_wday = ( days + 1 ) % 7; /* 24-sep-92 */ return( t ); } _WCRTLINK struct tm *_gmtime( const time_t *timer, struct tm *tm ) { tm->tm_isdst = 0; /* assume not */ return __brktime( DAYS_FROM_1900_TO_1970, *timer, 0L, tm ); } _WCRTLINK struct tm *gmtime( const time_t *timer ) { _INITTHETIME; return( _gmtime( timer, &_THE_TIME ) ); }