home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c082_144 / 2.ddi / CLIBSRC3.ZIP / CTIME.C < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-10  |  13.5 KB  |  462 lines

  1. /*------------------------------------------------------------------------
  2.  * filename - ctime.c
  3.  *
  4.  * function(s)
  5.  *    comtime   - converts long timedate to a structure
  6.  *    atime     - converts date and time to ASCII without trailing '\n'
  7.  *    asctime   - converts date and time to ASCII
  8.  *    ctime     - converts date and time to a string
  9.  *    gmtime    - converts date and time to Greenwich Mean Time
  10.  *    localtime - converts date and time to a structure
  11.  *    mktime    - normalizes the date and time structure
  12.  *    strftime  - converts date and time structure to a string
  13.  *-----------------------------------------------------------------------*/
  14.  
  15. /*
  16.  *      C/C++ Run Time Library - Version 5.0
  17.  *
  18.  *      Copyright (c) 1987, 1992 by Borland International
  19.  *      All Rights Reserved.
  20.  *
  21.  */
  22.  
  23.  
  24. #include <_io.h>
  25. #include <_printf.h>
  26. #include <time.h>
  27. #include <stdio.h>
  28. #include <string.h>
  29. #include <stdlib.h>
  30. #include <RtlData.h>
  31.  
  32. static const char Days[12] = {
  33.   31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
  34.   };
  35.  
  36. static int YDays[12] = {
  37.   0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
  38.   };
  39.  
  40. static char *SWeekday[7] = {
  41.   "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
  42.   };
  43.  
  44. static char *LWeekday[7] = {
  45.   "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"
  46.   };
  47.  
  48. static char *SMonth[12] = {
  49.   "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  50.   "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
  51.   };
  52.  
  53. static char *LMonth[12] = {
  54.   "January", "February", "March",     "April",   "May",      "June",
  55.   "July",    "August",   "September", "October", "November", "December"
  56.   };
  57.  
  58. static char *AmPm[2] = {
  59.   "AM", "PM"
  60.   };
  61.  
  62. #if !defined( _RTLDLL )
  63. static  struct  tm tmX;
  64. #endif
  65.  
  66. /*---------------------------------------------------------------------*
  67.  
  68. Name            comtime
  69.  
  70. Usage           static struct tm *comtime(unsigned long time, int dst);
  71.  
  72. Prototype in    local to this module
  73.  
  74. Description     fills the time structure tm by translating the long
  75.                 time.
  76.  
  77. Return value    the broken down time structure. This structure is
  78.                 a static which is overwritten with each call.
  79.  
  80. *---------------------------------------------------------------------*/
  81. static  struct  tm *comtime(time_t time, int dst)
  82. {
  83.     int      hpery;
  84.     unsigned i;
  85.     unsigned cumdays;
  86.     _QRTLDataBlock;
  87.  
  88.     if (time < 0)
  89.         time = 0;
  90.  
  91.     _QRTLInstanceData(tmX).tm_sec = (int)(time % 60);
  92.     time /= 60;                             /* Time in minutes */
  93.     _QRTLInstanceData(tmX).tm_min = (int)(time % 60);
  94.     time /= 60;                             /* Time in hours */
  95.     i = (unsigned)(time / (1461L * 24L));   /* Number of 4 year blocks */
  96.     _QRTLInstanceData(tmX).tm_year = (i << 2);
  97.     _QRTLInstanceData(tmX).tm_year+= 70;
  98.     cumdays = 1461 * i;
  99.     time %= 1461L * 24L;        /* Hours since end of last 4 year block */
  100.  
  101.     for (;;)
  102.         {
  103.         hpery = 365 * 24;
  104.         if ((_QRTLInstanceData(tmX).tm_year & 3) == 0)
  105.             hpery += 24;
  106.         if (time < hpery)
  107.             break;
  108.         cumdays += hpery / 24;
  109.         _QRTLInstanceData(tmX).tm_year++;
  110.         time -= hpery;
  111.         }   /* at end, time is number of hours into current year */
  112.  
  113.     if  (dst && daylight &&
  114.              __isDST( (int)(time % 24), (int)(time / 24), 0, _QRTLInstanceData(tmX).tm_year-70))
  115.         {
  116.         time++;
  117.         _QRTLInstanceData(tmX).tm_isdst = 1;
  118.         }
  119.     else
  120.         _QRTLInstanceData(tmX).tm_isdst = 0;
  121.  
  122.     _QRTLInstanceData(tmX).tm_hour = (int)(time % 24);
  123.     time /= 24;             /* Time in days */
  124.     _QRTLInstanceData(tmX).tm_yday = (int)time;
  125.     cumdays += (int)time + 4;
  126.     _QRTLInstanceData(tmX).tm_wday = cumdays % 7;
  127.     time++;
  128.  
  129.     if ((_QRTLInstanceData(tmX).tm_year & 3) == 0)
  130.         {
  131.         if (time > 60)
  132.             time--;
  133.         else
  134.             if (time == 60)
  135.                 {
  136.                 _QRTLInstanceData(tmX).tm_mon = 1;
  137.                 _QRTLInstanceData(tmX).tm_mday = 29;
  138.                 return(&_QRTLInstanceData(tmX));
  139.                 }
  140.         }
  141.  
  142.     for (_QRTLInstanceData(tmX).tm_mon = 0; Days[_QRTLInstanceData(tmX).tm_mon] < time; _QRTLInstanceData(tmX).tm_mon++)
  143.         time -= Days[_QRTLInstanceData(tmX).tm_mon];
  144.  
  145.     _QRTLInstanceData(tmX).tm_mday = (int)(time);
  146.     return(&_QRTLInstanceData(tmX));
  147. }
  148.  
  149.  
  150. /*------------------------------------------------------------------------*
  151.  
  152. Name            atime - converts date and time to ASCII without trailing '\n'
  153.  
  154. Usage           #include <time.h>
  155.                 static int atime( char *dest, const struct tm *tmPtr );
  156.  
  157.                 Local to this module
  158.  
  159. Description     Provides the basic formatting capabilities for asctime() and
  160.                 strftime( "%c" ).  These two functions both provide an ASCII
  161.                 version of the date and time in the struct tm, but asctime()
  162.                 adds a newline to the end.
  163.  
  164. Return value    Returns the number of characters in the ASCII string
  165.  
  166. *---------------------------------------------------------------------------*/
  167.  
  168. static int _FARFUNC atime( char *dest, const struct tm *tmPtr )
  169. {
  170.     return sprintf( dest, "%s %s %02d %02d:%02d:%02d %4d",
  171.         SWeekday[tmPtr->tm_wday],
  172.         SMonth[tmPtr->tm_mon],
  173.         tmPtr->tm_mday,
  174.         tmPtr->tm_hour,
  175.         tmPtr->tm_min,
  176.         tmPtr->tm_sec,
  177.         tmPtr->tm_year + 1900
  178.         );
  179. }
  180.  
  181. /*------------------------------------------------------------------------*
  182.  
  183. Name            asctime   - converts date and time to ASCII
  184.                 ctime     - converts date and time to a string
  185.                 gmtime    - converts date and time to Greenwich Mean Time
  186.                 localtime - converts date and time to a structure
  187.  
  188. Usage           #include <time.h>
  189.                 char *asctime(struct tm *_QRTLInstanceData(tmX));
  190.                 char *ctime(long *clock);
  191.                 struct tm *gmtime(long *clock);
  192.                 struct tm *localtime(long *clock);
  193.  
  194. Prototype in    time.h
  195.  
  196. Description     asctime  converts  a  time  stored  as  a  structure  to  a
  197.                 26-character string in the following form:
  198.  
  199.                 Mon Nov 21 11:31:54 1983\n\0
  200.  
  201.                 All the fields have a constant width.
  202.  
  203.                 ctime converts a time pointed to by clock (such as returned
  204.                 by the function time) to  a 26-character string of the form
  205.                 described above.
  206.  
  207.                 localtime   and  gmtime   return  pointers   to  structures
  208.                 containing the broken-down time. localtime corrects for the
  209.                 time  zone  and  possible  daylight  savings  time;  gmtime
  210.                 converts directly to GMT.
  211.  
  212.                 The global  long variable timezone contains  the difference
  213.                 in  seconds between  GMT and  local standard  time (in EST,
  214.                 timezone  is  5*60*60).  The  global  variable  daylight is
  215.                 non-zero  if  and  only  if  the  standard  U.S.A. Daylight
  216.                 Savings Time conversion should be applied.
  217.  
  218. Return value    asctime and ctime return a  pointer to the character string
  219.                 containing the date and time. This string is a static which
  220.                 is overwritten with each call.
  221.  
  222.                 gmtime and localtime return the broken down time structure.
  223.                 This structure is  a static which is overwritten  with each
  224.                 call.
  225.  
  226. *---------------------------------------------------------------------------*/
  227. struct  tm      *_FARFUNC gmtime(const time_t *clock)
  228. {
  229.     return(comtime(*clock, 0));
  230. }
  231.  
  232. struct  tm      *_FARFUNC localtime(const time_t *clock)
  233. {
  234.     unsigned long    x;
  235.  
  236.     tzset();        /* get timezone info */
  237.     x = *clock - timezone;
  238.     return(comtime(x, 1));
  239. }
  240.  
  241. char    *_FARFUNC asctime(const struct tm *tmPtr)
  242. {
  243. #if !defined( _RTLDLL )
  244.     static char a[26];
  245. #endif
  246.     int end;
  247.     _QRTLDataBlock;
  248.  
  249.     end = atime( _QRTLInstanceData(a), tmPtr );
  250.     _QRTLInstanceData(a)[end++] = '\n';        //  add terminating newline
  251.     _QRTLInstanceData(a)[end] = '\0';
  252.  
  253.     return(_QRTLInstanceData(a));
  254. }
  255.  
  256. char    * _FARFUNC ctime(const time_t *clock)
  257. {
  258.     return(asctime(localtime(clock)));
  259. }
  260.  
  261.  
  262. /*------------------------------------------------------------------------*
  263.     Converts a date expressed in local time to the number of seconds
  264.     elapsed since year 70 (1970) in calendar time.
  265.     All arguments are zero based.
  266.  *------------------------------------------------------------------------*/
  267. static unsigned long near totalsec(int year, int month, int day, int hour, int min, int sec)
  268. {
  269.     int leaps;
  270.     time_t days, secs;
  271.  
  272.     if (year < 70 || year > 138)
  273.         return ((time_t) -1);
  274.  
  275.     min += sec / 60;
  276.     sec %= 60;              /* Seconds are normalized */
  277.     hour += min / 60;
  278.     min %= 60;              /* Minutes are normalized */
  279.     day += hour / 24;
  280.     hour %= 24;             /* Hours are normalized   */
  281.  
  282.     year += month / 12;     /* Normalize month (not necessarily final) */
  283.     month %= 12;
  284.  
  285.     while (day >= Days[month])
  286.         {
  287.         if (!(year & 3) && (month ==1))
  288.             {
  289.             if (day > 28)
  290.                 {
  291.                 day -= 29;
  292.                 month++;
  293.                 }
  294.         else
  295.         break;
  296.             }
  297.         else
  298.             {
  299.             day -= Days[month];
  300.             month++;
  301.             }
  302.         year += month / 12; /* Normalize month */
  303.         month %= 12;
  304.         }
  305.  
  306.     year -= 70;
  307.     leaps = (year + 2) / 4;
  308.  
  309.     if (!((year+70) & 3) && (month < 2))
  310.         --leaps;
  311.  
  312.     days = year*365L + leaps + YDays[month] + day;
  313.  
  314.     secs = days*86400L + hour*3600L + min*60L + sec + timezone;
  315.  
  316.     if (daylight && __isDST(hour, day, month+1, year))
  317.         secs -= 3600;
  318.  
  319.     return(secs > 0 ? secs : (time_t) -1);
  320. }
  321.  
  322.  
  323. time_t _FARFUNC mktime(struct tm *t)
  324. {
  325.     time_t secs;
  326.  
  327.     secs = totalsec(t->tm_year, t->tm_mon, t->tm_mday-1, t->tm_hour, t->tm_min, t->tm_sec);
  328.  
  329.     if (secs != (time_t) -1){
  330.         localtime(&secs);
  331.         *t = _RTLInstanceData(tmX);
  332.     }
  333.  
  334.     return(secs);
  335. }
  336.  
  337.  
  338. size_t _FARFUNC strftime( char *s, size_t maxsize, const char *fmt, const struct tm *t )
  339.   {
  340.   char buf[ 25 ];
  341.  
  342.   char *p = buf;
  343.   int i, len;
  344.  
  345.   for( len = 1; len < maxsize && *fmt; ++fmt, p = buf )
  346.     {
  347.     if( *fmt != '%' )
  348.       {
  349.       ++len;
  350.       *s++ = *fmt;
  351.       }
  352.     else
  353.       {
  354.       strcpy( buf, "00" );
  355.  
  356.       switch( *++fmt )
  357.         {
  358.         case 'a':
  359.             p = SWeekday[t->tm_wday];
  360.             break;
  361.         case 'A':
  362.             p = LWeekday[t->tm_wday];
  363.             break;
  364.         case 'b':
  365.             p = SMonth[t->tm_mon];
  366.             break;
  367.         case 'B':
  368.             p = LMonth[t->tm_mon];
  369.             break;
  370.         case 'c':
  371.             atime( p, t );
  372.             break;
  373.         case 'd':
  374.             __utoa( t->tm_mday, buf + (t->tm_mday < 10) );
  375.             break;
  376.         case 'H':
  377.             __utoa( t->tm_hour, buf + (t->tm_hour < 10) );
  378.             break;
  379.         case 'I':
  380.             i = t->tm_hour % 12;
  381.             if (i == 0)
  382.                 i = 12;
  383.             __utoa( i, buf + (i < 10) );
  384.             break;
  385.         case 'j':
  386.             i = t->tm_yday + 1;
  387.             __utoa( i, buf + (i < 10) + (i < 100) );
  388.             break;
  389.         case 'm':
  390.             i = t->tm_mon + 1;
  391.             __utoa( i, buf + (i < 10) );
  392.             break;
  393.         case 'M':
  394.             __utoa( t->tm_min, buf + (t->tm_min < 10) );
  395.             break;
  396.         case 'p':
  397.             p = AmPm[ t->tm_hour / 12 ];
  398.             break;
  399.         case 'S':
  400.             __utoa( t->tm_sec, buf + (t->tm_sec < 10) );
  401.             break;
  402.         case 'U':
  403.             i = t->tm_wday - (t->tm_yday % 7);
  404.             if( i < 0 )
  405.                 i += 7;
  406.             i = (t->tm_yday + i) / 7;
  407.             __utoa( i, buf + (i < 10) );
  408.             break;
  409.         case 'w':
  410.             __utoa( t->tm_wday, buf );
  411.             break;
  412.         case 'W':
  413.             i = t->tm_wday - (t->tm_yday % 7);
  414.             if( i < 0 )
  415.                 i += 7;
  416.             i = (t->tm_yday + i - 1) / 7;
  417.             __utoa( i, buf + (i < 10) );
  418.             break;
  419.         case 'x':
  420.             strcpy( buf, SWeekday[t->tm_wday] );
  421.             strcat( buf, " " );
  422.             strcat( buf, SMonth[t->tm_mon] );
  423.             strcat( buf, " " );
  424.             __utoa( t->tm_mday, buf + strlen( buf ) );
  425.             strcat( buf, ", " );
  426.             __utoa( t->tm_year + 1900, buf + strlen( buf ) );
  427.             break;
  428.  
  429.         case 'X':
  430.             __utoa( t->tm_hour, buf + (t->tm_hour < 10) );
  431.             strcat( buf, ":0" );
  432.             __utoa( t->tm_min, buf + strlen( buf ) - (t->tm_min > 9) );
  433.             strcat( buf, ":0" );
  434.             __utoa( t->tm_sec, buf + strlen( buf ) - (t->tm_sec > 9) );
  435.             break;
  436.         case 'y':
  437.             i = t->tm_year % 100;
  438.             __utoa( i, buf + (i < 10) );
  439.             break;
  440.         case 'Y':
  441.             __utoa( 1900 + t->tm_year, buf );
  442.             break;
  443.         case 'Z':
  444.             p = tzname[ t->tm_isdst ];
  445.             break;
  446.         case '%':
  447.             p = "%";
  448.         }
  449.  
  450.       i = min( strlen( p ), maxsize - len );
  451.       strncpy( s, p, i );
  452.       len += i;
  453.       s += i;
  454.       }
  455.     }
  456.  
  457.   *s = '\0';
  458.  
  459.   if( *fmt )  return( 0 );
  460.   else        return( len - 1 );
  461.   }
  462.