0,0 → 1,141 |
/**************************************************************************** |
* |
* 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 ) ); |
} |