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 | }>>> |