forked from KolibriOS/kolibrios
update CLib
git-svn-id: svn://kolibrios.org@614 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
141
programs/develop/open watcom/trunk/clib/time/gmtime.c
Normal file
141
programs/develop/open watcom/trunk/clib/time/gmtime.c
Normal file
@@ -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 ) );
|
||||
}
|
Reference in New Issue
Block a user