Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
614 serge 1
/****************************************************************************
2
*
3
*                            Open Watcom Project
4
*
5
*    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
6
*
7
*  ========================================================================
8
*
9
*    This file contains Original Code and/or Modifications of Original
10
*    Code as defined in and that are subject to the Sybase Open Watcom
11
*    Public License version 1.0 (the 'License'). You may not use this file
12
*    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
13
*    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
14
*    provided with the Original Code and Modifications, and is also
15
*    available at www.sybase.com/developer/opensource.
16
*
17
*    The Original Code and all software distributed under the License are
18
*    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
19
*    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
20
*    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
21
*    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
22
*    NON-INFRINGEMENT. Please see the License for the specific language
23
*    governing rights and limitations under the License.
24
*
25
*  ========================================================================
26
*
27
* Description:  __brktime() is an internal function to convert time to struct tm
28
*
29
****************************************************************************/
30
 
31
#include "variety.h"
32
#include 
33
#include "thetime.h"
34
#include "timedata.h"
35
 
36
// #define DAYS_IN_4_YRS   ( 365 + 365 + 365 + 366 )
37
// #define DAYS_IN_400_YRS ( ( 100 * DAYS_IN_4_YRS ) - 3 )
38
 
39
//  #define SECONDS_PER_DAY ( 24 * 60 * 60 )
40
//  extern  short   __diyr[], __dilyr[];
41
 
42
/*
43
 The number of leap years from year 1 to year 1900 is 460.
44
 The number of leap years from year 1 to current year is
45
 expressed by "years/4 - years/100 + years/400". To determine
46
 the number of leap years from current year to 1900, we subtract
47
 460 from the formula result. We do this since "days" is the
48
 number of days since 1900.
49
*/
50
 
51
static unsigned long __DaysToJan1( unsigned year )
52
{
53
    unsigned    years = 1900 + year - 1;
54
    unsigned    leap_days = years / 4 - years / 100 + years / 400 - 460;
55
 
56
    return( year * 365UL + leap_days );
57
}
58
 
59
/*  __brktime breaks down a calendar time (clock) into a struct tm t */
60
 
61
struct tm *__brktime( unsigned long     days,
62
                      time_t            wallclock,
63
                      long              gmtdelta,       // localtime - gmtime
64
                      struct tm         *t )
65
{
66
    unsigned long       secs;
67
    unsigned            year;
68
    int                 day_of_year;
69
    int                 month;
70
    short const         *month_start;
71
 
72
    /*
73
        If date is Jan 1, 1970 0:00 to 12:00 UTC and we are west of UTC
74
        then add a day to wallclock, subtract the gmtdelta value, and
75
        decrement the calculated days. This prevents local times
76
        such as "Wed Dec 31 19:00:00 1969 (EST)" from being
77
        erroneously reported as "Sun Feb 6 01:28:16 2106 (EST)"
78
        since (wallclock - gmtdelta) wraps (i.e., wallclock < gmtdelta).
79
    */
80
    if( wallclock < 12 * 60 * 60UL && gmtdelta > 0 )
81
        wallclock += SECONDS_PER_DAY, days--; /* days compensated for wallclock one day ahead */
82
    wallclock -= ( time_t ) gmtdelta;
83
    days      += wallclock / SECONDS_PER_DAY;
84
    secs       = wallclock % SECONDS_PER_DAY;
85
    t->tm_hour = ( int ) ( secs / 3600 ) ;
86
    secs       = secs % 3600;
87
    t->tm_min  = ( int ) ( secs / 60 );
88
    t->tm_sec  = secs % 60;
89
 
90
    // The following two lines are not needed in the current implementation
91
    // because the range of values for days does not exceed DAYS_IN_400_YRS.
92
    // Even if it did, the algorithm still computes the correct values.
93
    //
94
    //    unsigned  year400s;
95
    //
96
    //    year400s = (days / DAYS_IN_400_YRS) * 400;
97
    //    days %= DAYS_IN_400_YRS;
98
    //
99
    // It is OK to reduce days to a value less than DAYS_IN_400_YRS, because
100
    // DAYS_IN_400_YRS is exactly divisible by 7. If it wasn't divisible by 7,
101
    // then the following line which appears at the bottom, should be computed
102
    // before the value of days is range reduced.
103
    //    t->tm_wday = (days + 1) % 7;                /* 24-sep-92 */
104
    //
105
    year = days / 365;
106
    day_of_year = ( int ) ( days - __DaysToJan1( year ) );
107
    while( day_of_year < 0 ) {
108
        --year;
109
        day_of_year += __leapyear( year + 1900 ) + 365;
110
    }
111
    // year += year400s;
112
 
113
    t->tm_yday = day_of_year;
114
    t->tm_year = ( int ) year;
115
    month_start = __diyr;
116
    if( __leapyear( year + 1900 ) )
117
        month_start = __dilyr;
118
    month = day_of_year / 31;               /* approximate month */
119
    if( day_of_year >= month_start[month + 1] )
120
        ++month;
121
    t->tm_mon  = month;
122
    t->tm_mday = day_of_year - month_start[month] + 1;
123
 
124
    /*  Calculate the day of the week */
125
    /*   Jan 1,1900 is a Monday */
126
 
127
    t->tm_wday = ( days + 1 ) % 7;                /* 24-sep-92 */
128
    return( t );
129
}
130
 
131
_WCRTLINK struct tm *_gmtime( const time_t *timer, struct tm *tm )
132
{
133
    tm->tm_isdst = 0;          /* assume not */
134
    return __brktime( DAYS_FROM_1900_TO_1970, *timer, 0L, tm );
135
}
136
 
137
_WCRTLINK struct tm *gmtime( const time_t *timer )
138
{
139
    _INITTHETIME;
140
    return( _gmtime( timer, &_THE_TIME ) );
141
}