Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  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 <time.h>
  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. }
  142.