Support rastport clipping rectangle for layerless rastports
[tangerine.git] / rom / dos / datetostr.c
blob580ee53f3827b1b114444f141fd3bdc1f4609c44
1 /*
2 Copyright © 1995-2001, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Convert a DateTime struct into strings.
6 Lang: english
7 */
8 #include "dos_intern.h"
9 #include "date.h"
11 #ifdef TEST
12 # include <proto/dos.h>
13 # include <stdio.h>
14 # undef AROS_LH1
15 # undef DateToStr
16 # undef AROS_LHA
17 # define AROS_LH1(ret,name,arg,type,base,offset,libname) \
18 ret name (arg)
19 # define AROS_LHA(type,name,reg) type name
20 #endif
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 /*****************************************************************************
46 NAME */
47 #include <dos/datetime.h>
48 #include <proto/dos.h>
50 AROS_LH1(BOOL, DateToStr,
52 /* SYNOPSIS */
53 AROS_LHA(struct DateTime *, datetime, D1),
55 /* LOCATION */
56 struct DosLibrary *, DOSBase, 124, Dos)
58 /* FUNCTION
59 DateToStr converts an AmigaDOS DateStamp to a human
60 readable ASCII string as requested by your settings in the
61 DateTime structure.
63 INPUTS
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.
103 RESULT
104 A zero return indicates that the DateStamp was invalid, and could
105 not be converted. Non-zero indicates that the call succeeded.
107 NOTES
109 EXAMPLE
110 See below.
112 BUGS
114 SEE ALSO
115 DateStamp(), StrtoDate()
117 INTERNALS
119 *****************************************************************************/
121 AROS_LIBFUNC_INIT
122 AROS_LIBBASE_EXT_DECL(struct DosLibrary *,DOSBase)
124 /* Starting days of the months in a leap year. */
126 STRPTR buf, fstring;
127 const UBYTE * name;
129 LONG year, month, days, mins, tick, leap=1;
131 /* Read time. */
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)
141 return DOSFALSE;
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).
166 days+=366+365;
167 year=4*(days/(366+3*365))+1976;
168 days%=(366+3*365);
170 /* Now divide the 4-year blocks into single years. */
171 if (days>=366)
173 leap=0;
174 days--;
175 year+=days/365;
176 days%=365;
179 else
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
185 100 is not.
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...
193 days-=17*365+5*366;
194 year=400*(days/(97*366+303*365))+2000;
195 days%=(97*366+303*365);
197 if(days>=366)
199 leap=0;
200 days--;
201 year+=100*(days/(24*366+76*365));
202 days%=(24*366+76*365);
204 if(days>=365)
206 leap=1;
207 days++;
208 year+=4*(days/(366+3*365));
209 days%=(366+3*365);
211 if(days>=366)
213 leap=0;
214 days--;
215 year+=days/365;
216 days%=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)
226 days++;
228 for(month=11;;month--)
230 if(days>=Dos_DayTable[month])
232 days-=Dos_DayTable[month];
233 break;
237 /* Remember that 0 means 1.1.1978. */
238 days++;
239 month++;
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;
257 DateStamp (&curr);
259 curr.ds_Days -= datetime->dat_Stamp.ds_Days;
261 if (curr.ds_Days >= -1 && curr.ds_Days <= 7)
263 fstring = "";
265 if (curr.ds_Days <= 1)
266 name = Dos_SubstDateTable[curr.ds_Days+1];
267 else
268 name = Dos_WeekTable[datetime->dat_Stamp.ds_Days%7];
270 while ((*buf++ = *name++) != 0);
274 if (*fstring)
276 while (*fstring)
278 switch(*fstring)
280 case 'y':
281 #if (AROS_FLAVOUR & AROS_FLAVOUR_BINCOMPAT)
282 *buf++ = year/10%10+'0';
283 *buf++ = year%10+'0';
284 #else
285 *buf++ = year/1000%10+'0';
286 *buf++ = year/100%10+'0';
287 *buf++ = year/10%10+'0';
288 *buf++ = year%10+'0';
289 #endif
290 break;
291 case 'm':
292 name=Dos_MonthTable[month-1];
293 while(*name)
294 *buf++=*name++;
295 break;
296 case 'M':
297 *buf++=month/10%10+'0';
298 *buf++=month%10+'0';
299 break;
300 case 'd':
301 *buf++=days/10%10+'0';
302 *buf++=days%10+'0';
303 break;
304 default:
305 *buf++=*fstring;
306 break;
309 fstring ++;
312 *buf = 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. */
331 return DOSTRUE;
332 AROS_LIBFUNC_EXIT
333 } /* DateToStr */
335 #ifdef TEST
337 # include <stdio.h>
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;
351 curr.dat_Flags = 0;
352 curr.dat_StrDay = day;
353 curr.dat_StrDate = date;
354 curr.dat_StrTime = time;
356 DateToStr (&curr);
358 printf ("Today is %s, %s. It's %s\n"
359 , day
360 , date
361 , time
364 curr.dat_Format = FORMAT_DEF;
366 DateToStr (&curr);
368 printf ("Local date: %s\n", date);
370 curr.dat_Flags = DTF_SUBST;
372 DateToStr (&curr);
374 printf ("Date with DTF_SUBST: %s\n", date);
376 curr.dat_Stamp.ds_Days ++;
378 DateToStr (&curr);
380 printf ("Date +1 with DTF_SUBST: %s\n", date);
382 curr.dat_Stamp.ds_Days ++;
384 DateToStr (&curr);
386 printf ("Date +2 with DTF_SUBST: %s\n", date);
388 curr.dat_Stamp.ds_Days ++;
390 DateToStr (&curr);
392 printf ("Date +3 with DTF_SUBST: %s\n", date);
394 curr.dat_Stamp.ds_Days -= 4;
396 DateToStr (&curr);
398 printf ("Date -1 with DTF_SUBST: %s\n", date);
400 curr.dat_Stamp.ds_Days --;
402 DateToStr (&curr);
404 printf ("Date -2 with DTF_SUBST: %s\n", date);
406 curr.dat_Stamp.ds_Days --;
408 DateToStr (&curr);
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;
416 DateToStr (&curr);
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;
424 DateToStr (&curr);
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;
432 DateToStr (&curr);
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;
440 DateToStr (&curr);
442 printf ("First Date: %s, %s. Time: %s\n", day, date, time);
444 return 0;
445 } /* main */
447 #endif /* TEST */