2 Copyright © 1995-2001, The AROS Development Team. All rights reserved.
5 Desc: Convert a DateTime struct into strings.
8 #include "dos_intern.h"
12 # include <proto/dos.h>
17 # define AROS_LH1(ret,name,arg,type,base,offset,libname) \
19 # define AROS_LHA(type,name,reg) type name
22 const ULONG Dos_DayTable
[]=
24 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335
27 const char *const Dos_MonthTable
[]=
29 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
30 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
33 const char *const Dos_WeekTable
[]=
35 "Sunday", "Monday", "Tuesday", "Wednesday",
36 "Thursday", "Friday", "Saturday"
39 const char *const Dos_SubstDateTable
[]=
41 "Tomorrow", "Today", "Yesterday"
44 /*****************************************************************************
47 #include <dos/datetime.h>
48 #include <proto/dos.h>
50 AROS_LH1(BOOL
, DateToStr
,
53 AROS_LHA(struct DateTime
*, datetime
, D1
),
56 struct DosLibrary
*, DOSBase
, 124, Dos
)
59 DateToStr converts an AmigaDOS DateStamp to a human
60 readable ASCII string as requested by your settings in the
64 DateTime - a pointer to an initialized DateTime structure. The
65 DateTime structure should be initialized as follows:
67 dat_Stamp: The datestamp to convert to ascii
69 dat_Format: How to convert the datestamp into
70 dat_StrDate. Can be any of the following:
72 FORMAT_DOS: AmigaDOS format (dd-mmm-yy). This
73 is the default if you specify something other
74 than any entry in this list.
76 FORMAT_INT: International format (yy-mmm-dd).
78 FORMAT_USA: American format (mm-dd-yy).
80 FORMAT_CDN: Canadian format (dd-mm-yy).
82 FORMAT_DEF default format for locale.
85 dat_Flags: Modifies dat_Format. The only flag
86 used by this function is DTF_SUBST. If set, then
87 a string like "Today" or "Monday" is generated
88 instead of the normal format if possible.
90 dat_StrDay: Pointer to a buffer to receive the day of
91 the week string. (Monday, Tuesday, etc.). If null,
92 this string will not be generated.
94 dat_StrDate: Pointer to a buffer to receive the date
95 string, in the format requested by dat_Format,
96 subject to possible modifications by DTF_SUBST. If
97 null, this string will not be generated.
99 dat_StrTime: Pointer to a buffer to receive the time
100 of day string. If NULL, this will not be generated.
104 A zero return indicates that the DateStamp was invalid, and could
105 not be converted. Non-zero indicates that the call succeeded.
115 DateStamp(), StrtoDate()
119 *****************************************************************************/
122 AROS_LIBBASE_EXT_DECL(struct DosLibrary
*,DOSBase
)
124 /* Starting days of the months in a leap year. */
129 LONG year
, month
, days
, mins
, tick
, leap
=1;
132 days
=datetime
->dat_Stamp
.ds_Days
;
133 mins
=datetime
->dat_Stamp
.ds_Minute
;
134 tick
=datetime
->dat_Stamp
.ds_Tick
;
137 Check if timestamp is correct. Correct timestamps lie
138 between the 1.1.1978 0:00:00 and the 11.7.5881588 23:59:59.
140 if(days
<0||(ULONG
)mins
>=24*60||(ULONG
)tick
>=TICKS_PER_SECOND
*60)
143 if(datetime
->dat_StrDay
!=NULL
)
145 /* Get weekday name. The 1.1.1978 was a sunday. */
146 buf
=datetime
->dat_StrDay
;
147 name
=Dos_WeekTable
[days
%7];
148 while((*buf
++=*name
++)!=0)
152 if(datetime
->dat_StrDate
!=NULL
)
155 Calculate year and the days in the year. Use a short method
156 if the date is between the 1.1.1978 and the 1.1.2100:
157 Every year even divisible by 4 in this time span is a leap year.
158 There are 92 normal and 30 leap years there.
160 if(days
<92*365+30*366)
163 1976 was a leap year so use it as a base to divide the days
164 into 4-year blocks (each beginning with a leap year).
167 year
=4*(days
/(366+3*365))+1976;
170 /* Now divide the 4-year blocks into single years. */
182 The rule for calendar calculations are:
183 1. Every year even divisible by 4 is a leap year.
184 2. As an exception from rule 1 every year even divisible by
186 3. Every year even divisible by 400 is a leap year as an
187 exception from rule 2.
188 So 1996, 2000 and 2004 are leap years - 1900 and 1999 are not.
190 Use 2000 as a base to devide the days into 400 year blocks,
191 those into 100 year blocks and so on...
194 year
=400*(days
/(97*366+303*365))+2000;
195 days
%=(97*366+303*365);
201 year
+=100*(days
/(24*366+76*365));
202 days
%=(24*366+76*365);
208 year
+=4*(days
/(366+3*365));
222 The starting-day table assumes a leap year - so add one day if
223 the date is after february 28th and the year is no leap year.
225 if(!leap
&&days
>=31+28)
228 for(month
=11;;month
--)
230 if(days
>=Dos_DayTable
[month
])
232 days
-=Dos_DayTable
[month
];
237 /* Remember that 0 means 1.1.1978. */
241 /* Build date string */
242 buf
=datetime
->dat_StrDate
;
244 switch (datetime
->dat_Format
)
246 case FORMAT_INT
: fstring
="y-m-d"; break;
247 case FORMAT_USA
: fstring
="M-d-y"; break;
248 case FORMAT_CDN
: fstring
="d-M-y"; break;
249 case FORMAT_DEF
: fstring
="d.M.y"; break;
250 default: fstring
="d-m-y"; break;
253 if (datetime
->dat_Flags
& DTF_SUBST
)
255 struct DateStamp curr
;
259 curr
.ds_Days
-= datetime
->dat_Stamp
.ds_Days
;
261 if (curr
.ds_Days
>= -1 && curr
.ds_Days
<= 7)
265 if (curr
.ds_Days
<= 1)
266 name
= Dos_SubstDateTable
[curr
.ds_Days
+1];
268 name
= Dos_WeekTable
[datetime
->dat_Stamp
.ds_Days
%7];
270 while ((*buf
++ = *name
++) != 0);
281 #if (AROS_FLAVOUR & AROS_FLAVOUR_BINCOMPAT)
282 *buf
++ = year
/10%10+'0';
283 *buf
++ = year
%10+'0';
285 *buf
++ = year
/1000%10+'0';
286 *buf
++ = year
/100%10+'0';
287 *buf
++ = year
/10%10+'0';
288 *buf
++ = year
%10+'0';
292 name
=Dos_MonthTable
[month
-1];
297 *buf
++=month
/10%10+'0';
301 *buf
++=days
/10%10+'0';
316 if(datetime
->dat_StrTime
!=NULL
)
318 /* Build time string */
319 datetime
->dat_StrTime
[0] = mins
/(10*60)+'0';
320 datetime
->dat_StrTime
[1] = mins
/60%10+'0';
321 datetime
->dat_StrTime
[2] = ':';
322 datetime
->dat_StrTime
[3] = mins
/10%6+'0';
323 datetime
->dat_StrTime
[4] = mins
%10+'0';
324 datetime
->dat_StrTime
[5] = ':';
325 datetime
->dat_StrTime
[6] = tick
/(10*TICKS_PER_SECOND
)+'0';
326 datetime
->dat_StrTime
[7] = tick
/TICKS_PER_SECOND
%10+'0';
327 datetime
->dat_StrTime
[8] = 0;
330 /* All done. Return OK. */
338 # include <dos/datetime.h>
339 # include <proto/dos.h>
341 int main (int argc
, char ** argv
)
343 struct DateTime curr
;
344 char day
[LEN_DATSTRING
];
345 char time
[LEN_DATSTRING
];
346 char date
[LEN_DATSTRING
];
348 DateStamp (&curr
.dat_Stamp
);
350 curr
.dat_Format
= FORMAT_DOS
;
352 curr
.dat_StrDay
= day
;
353 curr
.dat_StrDate
= date
;
354 curr
.dat_StrTime
= time
;
358 printf ("Today is %s, %s. It's %s\n"
364 curr
.dat_Format
= FORMAT_DEF
;
368 printf ("Local date: %s\n", date
);
370 curr
.dat_Flags
= DTF_SUBST
;
374 printf ("Date with DTF_SUBST: %s\n", date
);
376 curr
.dat_Stamp
.ds_Days
++;
380 printf ("Date +1 with DTF_SUBST: %s\n", date
);
382 curr
.dat_Stamp
.ds_Days
++;
386 printf ("Date +2 with DTF_SUBST: %s\n", date
);
388 curr
.dat_Stamp
.ds_Days
++;
392 printf ("Date +3 with DTF_SUBST: %s\n", date
);
394 curr
.dat_Stamp
.ds_Days
-= 4;
398 printf ("Date -1 with DTF_SUBST: %s\n", date
);
400 curr
.dat_Stamp
.ds_Days
--;
404 printf ("Date -2 with DTF_SUBST: %s\n", date
);
406 curr
.dat_Stamp
.ds_Days
--;
410 printf ("Date -3 with DTF_SUBST: %s\n", date
);
412 curr
.dat_Stamp
.ds_Days
= 0;
413 curr
.dat_Stamp
.ds_Minute
= 0;
414 curr
.dat_Stamp
.ds_Tick
= 0;
418 printf ("First Date: %s, %s. Time: %s\n", day
, date
, time
);
420 curr
.dat_Stamp
.ds_Days
= 0;
421 curr
.dat_Stamp
.ds_Minute
= 1;
422 curr
.dat_Stamp
.ds_Tick
= 0;
426 printf ("First Date + 1 Minute: %s, %s. Time: %s\n", day
, date
, time
);
428 curr
.dat_Stamp
.ds_Days
= 0;
429 curr
.dat_Stamp
.ds_Minute
= 0;
430 curr
.dat_Stamp
.ds_Tick
= 153;
434 printf ("First Date + 153 Ticks: %s, %s. Time: %s\n", day
, date
, time
);
436 curr
.dat_Stamp
.ds_Days
= 1;
437 curr
.dat_Stamp
.ds_Minute
= 0;
438 curr
.dat_Stamp
.ds_Tick
= 0;
442 printf ("First Date: %s, %s. Time: %s\n", day
, date
, time
);