added concrete implementations of putc(), getc(), getchar() and gets()
[tangerine.git] / workbench / libs / locale / formatdate.c
blob195d13c00902932815ce53012540d967fef18b42
1 /*
2 Copyright © 1995-2004, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc:
6 Lang: English
7 */
9 #include "locale_intern.h"
10 #include <exec/types.h>
11 #include <utility/hooks.h>
12 #include <utility/date.h>
13 #include <proto/utility.h>
14 #include <clib/alib_protos.h>
16 #include <stdio.h>
18 VOID PrintDigits(UWORD number, char fill, UWORD len, struct Hook *hook,
19 struct Locale *locale);
20 VOID _WriteChar(char token, struct Hook *hook, struct Locale *locale);
21 VOID _WriteString(STRPTR string, struct Hook *hook, struct Locale *locale);
23 static const ULONG dayspermonth[13] = {0 /* not used */,0,31,59,90,120,151,181,212,243,273,304,334};
25 /*****************************************************************************
27 NAME */
28 #include <proto/locale.h>
30 AROS_LH4(VOID, FormatDate,
32 /* SYNOPSIS */
33 AROS_LHA(struct Locale *, locale, A0),
34 AROS_LHA(STRPTR , formatString, A1),
35 AROS_LHA(struct DateStamp *, date, A2),
36 AROS_LHA(struct Hook *, hook, A3),
38 /* LOCATION */
39 struct LocaleBase *, LocaleBase, 10, Locale)
41 /* FUNCTION
43 Generate a date string based on a template. The bytes generated are sent
44 to a user specified callback function.
46 INPUTS
48 locale -- the locale to use when formatting the string
49 formatString -- the formatting template string; this is much like the
50 printf() formatting style, i.e. a % followed by a
51 formatting command. The following commands exist:
53 %a -- abbreviated weekday name
54 %A -- weekday name
55 %b -- abbreviated month name
56 %B -- month name
57 %c -- the same as "%a %b %d %H:%M:%S %Y"
58 %C -- the same as "%a %b %e %T %Z %Y"
59 %d -- day number with leading zeros
60 %D -- the same as "%m/%d/%y"
61 %e -- day number with leading spaces
62 %h -- abbreviated month name
63 %H -- hour using 24 hour style with leading zeros
64 %I -- hour using 12 hour style with leading zeros
65 %j -- julian date
66 %m -- month number with leading zeros
67 %M -- the number of minutes with leading zeros
68 %n -- linefeed
69 %p -- AM or PM string
70 %q -- hour using 24 hour style
71 %Q -- hour using 12 hour style
72 %r -- the same as "%I:%M:%S %p"
73 %R -- the same as "%H:%M"
74 %S -- the number of seconds with leading zeros
75 %t -- tab
76 %T -- the same as "%H:%M:%S"
77 %U -- the week number, taking Sunday as the first day
78 of the week
79 %w -- the weekday number
80 %W -- the week number, taking Monday as the first day
81 of the week
82 %x -- the same as "%m/%d/%y"
83 %X -- the same as "%H:%M:%S"
84 %y -- the year using two digits with leading zeros
85 %Y -- the year using four digits with leading zeros
87 If the template parameter is NULL, a single null byte
88 is sent to the callback function.
90 date -- the current date
91 hook -- callback function; this is called for every character
92 generated with the following arguments:
94 * pointer to hook structure
95 * character
96 * pointer to locale
98 RESULT
100 NOTES
102 EXAMPLE
104 BUGS
106 SEE ALSO
108 ParseDate(), <libraries/locale.h>
110 INTERNALS
112 HISTORY
114 17.01.2000 bergers implemented U & W, j is still missing
115 07.07.1999 SDuvan implemented (U, W, j not done yet)
117 *****************************************************************************/
119 AROS_LIBFUNC_INIT
121 struct ClockData cData;
122 ULONG week, days, tmp;
124 if(/* locale == NULL || */ hook == NULL)
125 return;
127 if(formatString == NULL)
129 _WriteChar(0, hook, locale);
130 return;
133 #warning Amiga2Date will fail around year 2114, because then the numer of seconds since 1978 dont fit in a 32 bit variable anymore!
135 Amiga2Date(date->ds_Days*86400 + date->ds_Minute*60 + date->ds_Tick / 50,
136 &cData);
138 while(*formatString != 0)
140 if(*formatString == '%')
142 switch(*(++formatString))
144 case 'a':
145 _WriteString(GetLocaleStr(locale, ABDAY_1 + cData.wday), hook,
146 locale);
147 break;
149 case 'A':
150 _WriteString(GetLocaleStr(locale, DAY_1 + cData.wday), hook,
151 locale);
152 break;
154 case 'b':
155 _WriteString(GetLocaleStr(locale, ABMON_1 + cData.month - 1),
156 hook, locale);
157 break;
159 case 'B':
160 _WriteString(GetLocaleStr(locale, MON_1 + cData.month - 1), hook,
161 locale);
162 break;
164 case 'c':
165 FormatDate(locale, "%a %b %d %H:%M:%S %Y", date, hook);
166 break;
168 case 'C':
169 FormatDate(locale, "%a %b %e %T %Z %Y", date, hook);
170 break;
172 case 'd':
173 PrintDigits(cData.mday, '0', 2, hook, locale);
174 break;
176 case 'x':
177 case 'D':
178 FormatDate(locale, "%m/%d/%y", date, hook);
179 break;
181 case 'e':
182 PrintDigits(cData.mday, ' ', 2, hook, locale);
183 break;
185 case 'h':
186 _WriteString(GetLocaleStr(locale, ABMON_1 + cData.month - 1),
187 hook, locale);
188 break;
190 case 'H':
191 PrintDigits(cData.hour, '0', 2, hook, locale);
192 break;
194 case 'I':
195 PrintDigits(cData.hour % 12, '0', 2, hook, locale);
196 break;
198 case 'j':
199 /* TODO */
200 #warning Julian date not tested.
201 /* Julian date is DDD (1 - 366)*/
202 PrintDigits(
203 cData.mday + dayspermonth[cData.month],
204 '0',
206 hook,
207 locale
209 break;
211 case 'm':
212 PrintDigits(cData.month, '0', 2, hook, locale);
213 break;
215 case 'M':
216 PrintDigits(cData.min, '0', 2, hook, locale);
217 break;
219 case 'n':
220 _WriteChar('\n', hook, locale);
221 break;
223 case 'p':
224 _WriteString(GetLocaleStr(locale,
225 cData.hour < 12 ? AM_STR : PM_STR),
226 hook, locale);
227 break;
229 case 'q':
230 PrintDigits(cData.hour, -1, 2, hook, locale);
231 break;
233 case 'Q':
234 PrintDigits(cData.hour % 12, -1, 2, hook, locale);
235 break;
237 case 'r':
238 FormatDate(locale, "%I:%M:%S %p", date, hook);
239 break;
241 case 'R':
242 FormatDate(locale, "%H:%M", date, hook);
243 break;
245 case 'S':
246 PrintDigits(cData.sec, '0', 2, hook, locale);
247 break;
249 case 't':
250 _WriteChar('\t', hook, locale);
251 break;
253 case 'X':
254 case 'T':
255 FormatDate(locale, "%H:%M:%S", date, hook);
256 break;
258 case 'W': /* week number, Monday first day of week */
259 case 'U': /* week number, Sunday first day of week */
260 days = cData.mday + dayspermonth[cData.month];
262 /* leap year ? */
263 if (0 == (cData.year % 4) && cData.month > 2)
266 ** 1700, 1800, 1900, 2100, 2200 re not leap years.
267 ** 2000 is a leap year.
268 ** -> if a year is divisible by 100 but not by 400 then
269 ** it is not a leap year!
271 if (0 == (cData.year % 100) && 0 != (cData.year % 400))
273 else
274 days++;
278 ** If January 1st is a Monday then the first week
279 ** will start with a Sunday January 7th if Sunday is the first day of the week
280 ** but if Monday is the first day of the week then Jan 1st will also be the
281 ** first day of the first week.
284 ** Go to Saturday = last day of week if Sunday is first day of week
285 ** Go to Sunday = last day of week if Monday is first day of week
287 if ('U' == *formatString)
289 /* Sunday is first day of the week */
290 tmp = days + (6 - cData.wday);
292 else
294 /* Monday is first day of week */
295 if (0 != cData.wday)
296 tmp = days + (7 - cData.wday);
297 else
298 tmp = days;
301 if (tmp < 7)
302 week = 0;
303 else
305 /* cut off the few days that belong to week 0 */
306 tmp -= (tmp % 7);
307 /* Calculate the full amount of weeks */
308 week = tmp / 7;
311 PrintDigits(week, '0', 2, hook, locale);
312 break;
314 case 'w':
315 PrintDigits(cData.wday, -1, 1, hook, locale);
316 break;
318 case 'y':
319 PrintDigits(cData.year % 100, '0', 2, hook, locale);
320 break;
322 case 'Y':
323 PrintDigits(cData.year, '0', 4, hook, locale);
324 break;
326 case 'Z':
327 /* cuurent time zone Unimplemented in 3.1 */
328 break;
330 case 0:
331 break;
333 default:
334 _WriteChar(*formatString, hook, locale);
335 break;
338 else
340 _WriteChar(*formatString, hook, locale);
343 formatString++;
346 _WriteChar(0, hook, locale); /* Write null terminator */
348 AROS_LIBFUNC_EXIT
349 } /* FormatDate */
352 VOID _WriteString(STRPTR string, struct Hook *hook, struct Locale *locale)
354 while(*string != 0)
356 _WriteChar(*string++, hook, locale);
361 VOID _WriteChar(char token, struct Hook *hook, struct Locale *locale)
363 AROS_UFC3(VOID, hook->h_Entry,
364 AROS_UFCA(struct Hook *, hook, A0),
365 AROS_UFCA(struct Locale *, locale, A2),
366 AROS_UFCA(char, token, A1)
371 VOID PrintDigits(UWORD number, char fill, UWORD len, struct Hook *hook,
372 struct Locale *locale)
374 char buf[7];
375 char *ptr = &buf[6];
376 int i = 0;
378 buf[6] = 0;
380 while((number || !i) && i < len)
382 *--ptr = number % 10 + '0';
383 number /= 10;
384 i++;
387 while(len - i > 0 && (char)-1 != fill)
389 len--;
390 _WriteChar(fill, hook, locale);
393 _WriteString((char *)ptr, hook, locale);