home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c065 / 1.ddi / CLIB1.ZIP / CTIME.C < prev    next >
Encoding:
C/C++ Source or Header  |  1990-06-07  |  10.8 KB  |  407 lines

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