forked from KolibriOS/kolibrios
update CLib
git-svn-id: svn://kolibrios.org@614 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
250
programs/develop/open watcom/trunk/clib/time/timeutil.c
Normal file
250
programs/develop/open watcom/trunk/clib/time/timeutil.c
Normal file
@@ -0,0 +1,250 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* 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: time utility functions
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include "variety.h"
|
||||
#include <time.h>
|
||||
#include "rtdata.h"
|
||||
#include "timedata.h"
|
||||
|
||||
static int time_less( const struct tm *t1, const struct tm *t2 );
|
||||
|
||||
static int calc_yday( const struct tm *timetm, int year )
|
||||
{
|
||||
struct tm tmptm;
|
||||
int month_days;
|
||||
int first_wday;
|
||||
int nth_week;
|
||||
short const *diyr;
|
||||
|
||||
if( timetm->tm_isdst == 0 ) { // M.m.n.d form
|
||||
diyr = ( __leapyear( ( unsigned ) year + 1900 ) ) ? __dilyr : __diyr;
|
||||
month_days = diyr[timetm->tm_mon + 1] - diyr[timetm->tm_mon];
|
||||
tmptm.tm_sec = 0;
|
||||
tmptm.tm_min = 0;
|
||||
tmptm.tm_hour = 0;
|
||||
tmptm.tm_mday = 1;
|
||||
tmptm.tm_mon = timetm->tm_mon;
|
||||
tmptm.tm_year = year;
|
||||
tmptm.tm_isdst = 0;
|
||||
( void ) mktime( &tmptm );
|
||||
first_wday = ( timetm->tm_wday - tmptm.tm_wday + 7 ) % 7;
|
||||
if( timetm->tm_mday == 5 ) {
|
||||
if( ( 1 + first_wday + ( timetm->tm_mday - 1 ) * 7 ) > month_days )
|
||||
nth_week = timetm->tm_mday - 2; // fifth req. weekday does not exist
|
||||
else
|
||||
nth_week = timetm->tm_mday - 1;
|
||||
} else
|
||||
nth_week = timetm->tm_mday - 1;
|
||||
return( tmptm.tm_yday + first_wday + nth_week * 7 );
|
||||
}
|
||||
if( timetm->tm_isdst == 1 ) /* if Jn form */
|
||||
return( timetm->tm_yday - 1 );
|
||||
return( timetm->tm_yday );
|
||||
}
|
||||
|
||||
/* determine if in souther hemisphere -> start is after end */
|
||||
static int check_order( const struct tm *start, const struct tm *end, int year )
|
||||
{
|
||||
int start_day;
|
||||
int end_day;
|
||||
|
||||
/* these quick checks should always be enough */
|
||||
if( ( start->tm_isdst == 0 ) && ( end->tm_isdst == 0 ) ) { // M.m.n.d form
|
||||
if( start->tm_mon > end->tm_mon )
|
||||
return( 1 );
|
||||
if( start->tm_mon < end->tm_mon )
|
||||
return( 0 );
|
||||
}
|
||||
/* start/end of daylight savings time is in the same month (rare case) */
|
||||
/* these are *expensive* calculations under NT since 2 TZ checks must be done */
|
||||
start_day = calc_yday( start, year );
|
||||
end_day = calc_yday( end, year );
|
||||
if( start_day > end_day )
|
||||
return( 1 );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/* determine if daylight savings time */
|
||||
int __isindst( struct tm *t )
|
||||
{
|
||||
int month;
|
||||
int dst;
|
||||
int n1;
|
||||
int n2;
|
||||
int month_days;
|
||||
int time_check;
|
||||
int south;
|
||||
struct tm const *start;
|
||||
struct tm const *end;
|
||||
short const *diyr;
|
||||
|
||||
// already determined -- if we are sure
|
||||
if( t->tm_isdst >= 0 )
|
||||
return( t->tm_isdst );
|
||||
dst = 0;
|
||||
// if zone doesn't have a daylight savings period
|
||||
if( _RWD_daylight == 0 )
|
||||
return( t->tm_isdst = dst );
|
||||
// // check for no daylight savings time rule
|
||||
// if( tzname[1][0] == '\0' ) { // doesn't work since Win32 says
|
||||
// return( t->tm_isdst = dst );// daylight zone name = standard zone name
|
||||
// }
|
||||
|
||||
south = check_order( &_RWD_start_dst, &_RWD_end_dst, t->tm_year );
|
||||
if( south ) {
|
||||
// if southern hemisphere
|
||||
// invert start and end dates and then invert return value
|
||||
start = &_RWD_end_dst;
|
||||
end = &_RWD_start_dst;
|
||||
} else {
|
||||
start = &_RWD_start_dst;
|
||||
end = &_RWD_end_dst;
|
||||
}
|
||||
month = t->tm_mon;
|
||||
diyr = ( __leapyear( ( unsigned ) t->tm_year + 1900 ) ) ? __dilyr : __diyr;
|
||||
month_days = diyr[month + 1] - diyr[month];
|
||||
time_check = 0;
|
||||
/*
|
||||
* M.m.n.d form
|
||||
* m = start->tm_mon (month 0-11)
|
||||
* n = start->tm_mday (n'th week day 1-5)
|
||||
* d = start->tm_wday (week day 0-6)
|
||||
*/
|
||||
if( start->tm_isdst == 0 ) { /* if Mm.n.d form */
|
||||
if( month > start->tm_mon )
|
||||
dst = 1; /* assume dst for now */
|
||||
else if( month == start->tm_mon ) {
|
||||
/* calculate for current day */
|
||||
n1 = t->tm_mday - ( t->tm_wday + 7 - start->tm_wday ) % 7;
|
||||
/* calculate for previous day */
|
||||
n2 = t->tm_mday - 1 - ( t->tm_wday - 1 + 7 - start->tm_wday ) % 7;
|
||||
// n_ stands for the day of the month that is past &&
|
||||
// is closest to today && is the required weekday
|
||||
if( start->tm_mday == 5 ) {
|
||||
if( n1 > month_days - 7 ) {
|
||||
dst = 1; /* assume dst for now */
|
||||
if( n2 <= month_days - 7 )
|
||||
time_check = 1;
|
||||
}
|
||||
} else {
|
||||
if( n1 >= 7 * ( start->tm_mday - 1 ) + 1 ) {
|
||||
dst = 1; /* assume dst for now */
|
||||
if( n2 < 7 * ( start->tm_mday - 1 ) + 1 )
|
||||
time_check = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
n1 = start->tm_yday;
|
||||
if( start->tm_isdst == 1 ) { /* if Jn form */
|
||||
if( __leapyear( ( unsigned ) t->tm_year + 1900 ) ) {
|
||||
if( n1 > __diyr[2] )
|
||||
n1++; /* past Feb 28 */
|
||||
}
|
||||
n1--;
|
||||
}
|
||||
if( t->tm_yday >= n1 ) {
|
||||
dst = 1; /* assume dst for now */
|
||||
if( t->tm_yday == n1 )
|
||||
time_check = 1;
|
||||
}
|
||||
}
|
||||
/* if it is the day for a switch-over then check the time too */
|
||||
if( time_check )
|
||||
dst = !time_less( t, start );
|
||||
|
||||
/* if we are certain that it is before daylight saving then return */
|
||||
if( dst == 0 ) {
|
||||
if( south )
|
||||
dst = south - dst; /* invert value of dst */
|
||||
return( t->tm_isdst = dst );
|
||||
}
|
||||
|
||||
/* now see if it is after daylight saving */
|
||||
time_check = 0;
|
||||
if( end->tm_isdst == 0 ) { /* if Mm.n.d form */
|
||||
if( month > end->tm_mon )
|
||||
dst = 0; /* not dst */
|
||||
else if( month == end->tm_mon ) {
|
||||
dst = 0;
|
||||
/* calculate for current day */
|
||||
n1 = t->tm_mday - ( t->tm_wday + 7 - end->tm_wday ) % 7;
|
||||
/* calculate for previous day */
|
||||
n2 = t->tm_mday - 1 -
|
||||
( t->tm_wday - 1 + 7 - end->tm_wday ) % 7;
|
||||
if( end->tm_mday == 5 ) {
|
||||
if( n1 <= month_days - 7 )
|
||||
dst = 1;
|
||||
else if( n2 <= month_days - 7 )
|
||||
time_check = 1;
|
||||
} else {
|
||||
if( n1 < 7 * ( end->tm_mday - 1 ) + 1 )
|
||||
dst = 1;
|
||||
else if( n2 < 7 * ( end->tm_mday - 1 ) + 1 )
|
||||
time_check = 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
n1 = end->tm_yday;
|
||||
if( end->tm_isdst == 1 ) { /* if Jn form */
|
||||
if( __leapyear( ( unsigned ) t->tm_year + 1900 ) ) {
|
||||
if( n1 > __diyr[2] )
|
||||
n1++; /* past Feb 28 */
|
||||
}
|
||||
n1--;
|
||||
}
|
||||
if( t->tm_yday >= n1 ) {
|
||||
dst = 0;
|
||||
if( t->tm_yday == n1 )
|
||||
time_check = 1;
|
||||
}
|
||||
}
|
||||
/* if it is the day for a switch-over then check the time too */
|
||||
if( time_check )
|
||||
dst = time_less( t, end );
|
||||
if( south )
|
||||
dst = south - dst; /* invert value of dst */
|
||||
return( t->tm_isdst = dst );
|
||||
}
|
||||
|
||||
static int time_less( const struct tm *t1, const struct tm *t2 )
|
||||
{
|
||||
int before;
|
||||
|
||||
before = 0;
|
||||
if( t1->tm_hour < t2->tm_hour )
|
||||
before = 1;
|
||||
else if( t1->tm_hour == t2->tm_hour ) {
|
||||
if( t1->tm_min < t2->tm_min
|
||||
|| t1->tm_min == t2->tm_min && t1->tm_sec < t2->tm_sec )
|
||||
before = 1;
|
||||
}
|
||||
return( before );
|
||||
}
|
Reference in New Issue
Block a user