home *** CD-ROM | disk | FTP | other *** search
/ Aminet 18 / aminetcdnumber181997.iso / Aminet / misc / emu / AROSdev.lha / AROS / rom / dos / datetostr.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-01-27  |  5.3 KB  |  237 lines

  1. /*
  2.     (C) 1995-96 AROS - The Amiga Replacement OS
  3.     $Id: datetostr.c,v 1.7 1997/01/27 00:36:16 ldp Exp $
  4.     $Log: datetostr.c,v $
  5.     Revision 1.7  1997/01/27 00:36:16  ldp
  6.     Polish
  7.  
  8.     Revision 1.6  1996/12/09 13:53:23  aros
  9.     Added empty templates for all missing functions
  10.  
  11.     Moved #include's into first column
  12.  
  13.     Revision 1.5  1996/11/21 10:49:47  aros
  14.     Created macros AROS_SLIB_ENTRY() for assembler files, too, to solve naming
  15.     problems.
  16.  
  17. The #includes
  18.     makedepend will ignore them (GCC works, though).
  19.  
  20.     Removed a couple of Logs
  21.  
  22.     Revision 1.4  1996/10/24 15:50:25  aros
  23.     Use the official AROS macros over the __AROS versions.
  24.  
  25.     Revision 1.3  1996/08/13 13:52:53  digulla
  26.     Replaced <dos/dosextens.h> by "dos_intern.h" or added "dos_intern.h"
  27.     Replaced AROS_LA by AROS_LHA
  28.  
  29.     Revision 1.2  1996/08/01 17:40:48  digulla
  30.     Added standard header for all files
  31.  
  32.     Desc:
  33.     Lang: english
  34. */
  35. #include <dos/datetime.h>
  36. #include "dos_intern.h"
  37.  
  38. /*****************************************************************************
  39.  
  40.     NAME */
  41. #include <proto/dos.h>
  42.  
  43.     AROS_LH1(BOOL, DateToStr,
  44.  
  45. /*  SYNOPSIS */
  46.     AROS_LHA(struct DateTime *, datetime, D1),
  47.  
  48. /*  LOCATION */
  49.     struct DosLibrary *, DOSBase, 124, Dos)
  50.  
  51. /*  FUNCTION
  52.  
  53.     INPUTS
  54.  
  55.     RESULT
  56.  
  57.     NOTES
  58.  
  59.     EXAMPLE
  60.  
  61.     BUGS
  62.  
  63.     SEE ALSO
  64.  
  65.     INTERNALS
  66.  
  67.     HISTORY
  68.     29-10-95    digulla automatically created from
  69.                 dos_lib.fd and clib/dos_protos.h
  70.  
  71. *****************************************************************************/
  72. {
  73.     AROS_LIBFUNC_INIT
  74.     AROS_LIBBASE_EXT_DECL(struct DosLibrary *,DOSBase)
  75.  
  76.     /* Starting days of the months in a leap year. */
  77.     const ULONG daytabl[]=
  78.     { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 };
  79.  
  80.     char *const monthtable[]=
  81.     { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  82.       "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
  83.  
  84.     char *const weektable[]=
  85.     { "Sunday", "Monday", "Tuesday", "Wednesday",
  86.       "Thursday", "Friday", "Saturday" };
  87.  
  88.     STRPTR buf, name, fstring;
  89.  
  90.     LONG year, month, days, mins, tick, leap=1;
  91.  
  92.     /* Read time. */
  93.     days=datetime->dat_Stamp.ds_Days;
  94.     mins=datetime->dat_Stamp.ds_Minute;
  95.     tick=datetime->dat_Stamp.ds_Tick;
  96.  
  97.     /*
  98.     Check if timestamp is correct. Correct timestamps lie
  99.     between the 1.1.1978 0:00:00 and the 11.7.5881588 23:59:59.
  100.     */
  101.     if(days<0||(ULONG)mins>=24*60||(ULONG)tick>=TICKS_PER_SECOND*60)
  102.     return 0;
  103.  
  104.     if(datetime->dat_StrDay!=NULL)
  105.     {
  106.     /* Get weekday name. The 1.1.1978 was a sunday. */
  107.     buf=datetime->dat_StrDay;
  108.     name=weektable[days%7];
  109.     while((*buf++=*name++)!=0)
  110.         ;
  111.     }
  112.  
  113.     if(datetime->dat_StrDate!=NULL)
  114.     {
  115.     /*
  116.         Calculate year and the days in the year. Use a short method
  117.         if the date is between the 1.1.1978 and the 1.1.2100:
  118.         Every year even divisible by 4 in this time span is a leap year.
  119.         There are 92 normal and 30 leap years there.
  120.     */
  121.     if(days<92*365+30*365)
  122.     {
  123.         /*
  124.         1976 was a leap year so use it as a base to divide the days
  125.         into 4-year blocks (each beginning with a leap year).
  126.         */
  127.         days+=366+365;
  128.         year=4*(days/(366+3*365))+1976;
  129.         days%=(366+3*365);
  130.         /* Now divide the 4-year blocks into single years. */
  131.         if(days>=366)
  132.         {
  133.         leap=0;
  134.         days--;
  135.         year+=days/365;
  136.         days%=365;
  137.         }
  138.     }else
  139.     {
  140.         /*
  141.         The rule for calendar calculations are:
  142.         1. Every year even divisible by 4 is a leap year.
  143.         2. As an exception from rule 1 every year even divisible by
  144.            100 is not.
  145.         3. Every year even divisible by 400 is a leap year as an
  146.            exception from rule 2.
  147.         So 1996, 2000 and 2004 are leap years - 1900 and 1999 are not.
  148.  
  149.         Use 2000 as a base to devide the days into 400 year blocks,
  150.         those into 100 year blocks and so on...
  151.         */
  152.         days-=17*365+5*366;
  153.         year=400*(days/(97*366+303*365))+2000;
  154.         days%=(97*366+303*365);
  155.         if(days>=366)
  156.         {
  157.         leap=0;
  158.         days--;
  159.         year+=100*(days/(24*366+76*365));
  160.         days%=(24*366+76*365);
  161.         if(days>=365)
  162.         {
  163.             leap=1;
  164.             days++;
  165.             year+=4*(days/(366+3*365));
  166.             days%=(366+3*365);
  167.             if(days>=366)
  168.             {
  169.             leap=0;
  170.             days--;
  171.             year+=days/365;
  172.             days%=365;
  173.             }
  174.         }
  175.         }
  176.     }
  177.     /*
  178.          The starting-day table assumes a leap year - so add one day if
  179.          the date is after february 28th and the year is no leap year.
  180.     */
  181.     if(!leap&&days>=31+28)
  182.         days++;
  183.     for(month=11;;month--)
  184.         if(days>=daytabl[month])
  185.         {
  186.         days-=daytabl[month];
  187.         break;
  188.         }
  189.     /* Remember that 0 means 1.1.1978. */
  190.     days++;
  191.  
  192.     /* Build date string */
  193.     buf=datetime->dat_StrDate;
  194.     fstring="d-m-y";
  195.     do
  196.         switch(*fstring)
  197.         {
  198.         case 'y':
  199.             *buf++=year/10%10+'0';
  200.             *buf++=year%10+'0';
  201.             break;
  202.         case 'm':
  203.             name=monthtable[month];
  204.             while(*name)
  205.             *buf++=*name++;
  206.             break;
  207.         case 'd':
  208.             *buf++=days/10+'0';
  209.             *buf++=days%10+'0';
  210.             break;
  211.         default:
  212.             *buf++=*fstring;
  213.             break;
  214.         }
  215.     while(*fstring++);
  216.     }
  217.  
  218.     if(datetime->dat_StrTime!=NULL)
  219.     {
  220.     /* Build time string */
  221.     datetime->dat_StrTime[0]=mins/(10*60)+'0';
  222.     datetime->dat_StrTime[1]=mins/60%10+'0';
  223.     datetime->dat_StrTime[2]=':';
  224.     datetime->dat_StrTime[3]=mins/10%6+'0';
  225.     datetime->dat_StrTime[4]=mins%10+'0';
  226.     datetime->dat_StrTime[5]=':';
  227.     datetime->dat_StrTime[6]=tick/(10*TICKS_PER_SECOND)+'0';
  228.     datetime->dat_StrTime[7]=tick/TICKS_PER_SECOND%10+'0';
  229.     datetime->dat_StrTime[8]=0;
  230.     }
  231.  
  232.     /* All done. Return OK. */
  233.     return 1;
  234.  
  235.     AROS_LIBFUNC_EXIT
  236. } /* DateToStr */
  237.