4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 1996 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1984 AT&T */
28 /* All Rights Reserved */
31 #pragma ident "%Z%%M% %I% %E% SMI"
33 #if !defined(lint) && defined(SCCSIDS)
34 static char *sccsid
= "%Z%%M% %I% %E% SMI"; /* from S5R3.1 cftime.c 1.9 */
42 #include <sys/param.h>
45 static char *getstr(/*char *p, char **strp*/);
48 extern char *getenv();
49 extern char *malloc();
50 extern int openlocale(/*char *category, int cat_id, char *locale, char *newlocale */);
51 extern void init_statics();
53 extern struct dtconv
*_dtconv
;
54 extern char _locales
[MAXLOCALE
+ 1][MAXLOCALENAME
+ 1];
55 extern char _my_time
[];
57 char *dtconv_str
= NULL
;
58 char *getlocale_time();
61 strftime(buf
, maxsize
, format
, tm
)
65 register char *cp
, *p
, c
;
68 register struct dtconv
*dtcp
;
70 (void) getlocale_time();
71 dtcp
= localdtconv(); /* get locale's strings */
73 /* Build date string by parsing format string */
76 while ((c
= *format
++) != '\0') {
80 case '%': /* Percent sign */
81 if (++size
>= maxsize
)
86 case 'a': /* Abbreviated weekday name */
87 for (p
= dtcp
->abbrev_weekday_names
[tm
->tm_wday
];
89 if (++size
>= maxsize
)
95 case 'A': /* Weekday name */
96 for (p
= dtcp
->weekday_names
[tm
->tm_wday
];
98 if (++size
>= maxsize
)
105 case 'b': /* Abbreviated month name */
106 for (p
= dtcp
->abbrev_month_names
[tm
->tm_mon
];
108 if (++size
>= maxsize
)
114 case 'B': /* Month name */
115 for (p
= dtcp
->month_names
[tm
->tm_mon
];
117 if (++size
>= maxsize
)
123 case 'c': /* date and time representation */
124 i
= strftime(cp
, maxsize
- size
, "%x %X", tm
);
131 case 'C': /* long date and time representation */
132 i
= strftime(cp
, maxsize
- size
,
133 dtcp
->ldate_format
, tm
);
140 case 'd': /* Day of month, with leading zero */
141 if ((size
+= 2) >= maxsize
)
143 cp
= itoa(tm
->tm_mday
, cp
, 2);
146 case 'D': /* Shorthand for %m/%d/%y */
147 i
= strftime(cp
, maxsize
- size
, "%m/%d/%y",
155 case 'e': /* Day of month without leading zero */
156 if ((size
+= 2) >= maxsize
)
158 if (tm
->tm_mday
< 10) {
160 cp
= itoa(tm
->tm_mday
, cp
, 1);
162 cp
= itoa(tm
->tm_mday
, cp
, 2);
165 case 'H': /* Hour (24 hour version) */
166 if ((size
+= 2) >= maxsize
)
168 cp
= itoa(tm
->tm_hour
, cp
, 2);
171 case 'I': /* Hour (12 hour version) */
172 if ((size
+= 2) >= maxsize
)
174 cp
= itoa(tm
->tm_hour
> 12 ?
176 (tm
->tm_hour
== 0 ? 12 : tm
->tm_hour
),
180 case 'j': /* Julian date */
181 if ((size
+= 3) >= maxsize
)
183 cp
= itoa(tm
->tm_yday
+ 1, cp
, 3);
186 case 'k': /* Hour (24 hour version) */
187 if ((size
+= 2) >= maxsize
)
189 if (tm
->tm_hour
< 10) {
191 cp
= itoa(tm
->tm_hour
, cp
, 1);
193 cp
= itoa(tm
->tm_hour
, cp
, 2);
196 case 'l': /* Hour (12 hour version) */
197 if ((size
+= 2) >= maxsize
)
199 temp
= tm
->tm_hour
> 12 ?
201 (tm
->tm_hour
== 0 ? 12 : tm
->tm_hour
);
204 cp
= itoa(temp
, cp
, 1);
206 cp
= itoa(temp
, cp
, 2);
209 case 'm': /* Month number */
210 if ((size
+= 2) >= maxsize
)
212 cp
= itoa(tm
->tm_mon
+ 1, cp
, 2);
215 case 'M': /* Minute */
216 if ((size
+= 2) >= maxsize
)
218 cp
= itoa(tm
->tm_min
, cp
, 2);
221 case 'n': /* Newline */
222 if (++size
>= maxsize
)
227 case 'p': /* AM or PM */
228 if (tm
->tm_hour
>= 12)
232 for (; *p
!= '\0'; p
++) {
233 if (++size
>= maxsize
)
239 case 'r': /* Shorthand for %I:%M:%S AM or PM */
240 i
= strftime(cp
, maxsize
- size
, "%I:%M:%S %p",
248 case 'R': /* Time as %H:%M */
249 i
= strftime(cp
, maxsize
- size
, "%H:%M", tm
);
256 case 'S': /* Seconds */
257 if ((size
+= 2) >= maxsize
)
259 cp
= itoa(tm
->tm_sec
, cp
, 2);
263 if (++size
>= maxsize
)
268 case 'T': /* Shorthand for %H:%M:%S */
269 i
= strftime(cp
, maxsize
- size
, "%H:%M:%S",
277 case 'U': /* Weekday number, taking Sunday as
278 * the first day of the week */
279 if ((size
+= 2) >= maxsize
)
281 temp
= tm
->tm_yday
- tm
->tm_wday
;
283 i
= (temp
+ 1) / 7 + 1; /* +1 for - tm->tm_wday */
291 case 'w': /* Weekday number */
292 if (++size
>= maxsize
)
294 cp
= itoa(tm
->tm_wday
, cp
, 1);
297 case 'W': /* Week number of year, taking Monday as
298 * first day of week */
299 if ((size
+= 2) >= maxsize
)
301 if (tm
->tm_wday
== 0)
302 temp
= tm
->tm_yday
- 6;
304 temp
= tm
->tm_yday
- tm
->tm_wday
+ 1;
306 i
= (temp
+ 1) / 7 + 1; /* 1 for
311 i
= 52; /* less than 4 days in the first
312 week causes it to belong to
313 the tail of prev year */
317 case 'x': /* Localized date format */
318 i
= strftime(cp
, maxsize
- size
,
319 dtcp
->sdate_format
, tm
);
326 case 'X': /* Localized time format */
327 i
= strftime(cp
, maxsize
- size
,
328 dtcp
->time_format
, tm
);
335 case 'y': /* Year in the form yy */
336 if ((size
+= 2) >= maxsize
)
338 cp
= itoa((tm
->tm_year
% 100), cp
, 2);
341 case 'Y': /* Year in the form ccyy */
342 if ((size
+= 4) >= maxsize
)
344 cp
= itoa(1900 + tm
->tm_year
, cp
, 4);
347 case 'Z': /* Timezone */
348 for(p
= tm
->tm_zone
; *p
!= '\0'; p
++) {
349 if (++size
>= maxsize
)
356 if ((size
+= 2) >= maxsize
)
359 *cp
++ = *(format
- 1);
363 if (++size
>= maxsize
)
380 *ptr
++ = i
/ 1000 + '0';
381 i
= i
- i
/ 1000 * 1000;
383 *ptr
++ = i
/ 100 + '0';
384 i
= i
- i
/ 100 * 100;
386 *ptr
++ = i
/ 10 + '0';
388 *ptr
++ = i
% 10 + '0';
402 struct dtconv dtconvp
;
403 char temp
[MAXLOCALENAME
+ 1];
405 if (_locales
[0][0] == '\0')
408 /* Here we use the string newlocales to set time constants
409 * which should have been saved
410 * from a previous call to setlocale. We deferred the read until now
413 if (strcmp(_my_time
, _locales
[LC_TIME
-1]) == 0) {
414 if (dtconv_str
== NULL
) {
416 * Below is executed if getlocale_time()
417 * is called when LC_TIME locale is initial
422 * Just to make openlocale() to read LC_TIME file.
424 strcat(_locales
[LC_TIME
-1], temp
);
429 strcpy(temp
, _locales
[LC_TIME
- 1]);
430 strcpy(_locales
[LC_TIME
- 1], _my_time
);
432 if ((fd
= openlocale("LC_TIME", LC_TIME
, temp
, _locales
[LC_TIME
- 1])) < 0)
434 strcpy(_my_time
, _locales
[LC_TIME
- 1]);
437 if ((fstat(fd
, &buf
)) != 0)
439 if ((str
= malloc((unsigned)buf
.st_size
+ 2)) == NULL
) {
444 if ((read(fd
, str
, (int)buf
.st_size
)) != buf
.st_size
) {
450 /* Set last character of str to '\0' */
451 p
= &str
[buf
.st_size
];
455 /* p will "walk thru" str */
458 for (i
= 0; i
< 12; i
++) {
459 p
= getstr(p
, &dtconvp
.abbrev_month_names
[i
]);
463 for (i
= 0; i
< 12; i
++) {
464 p
= getstr(p
, &dtconvp
.month_names
[i
]);
468 for (i
= 0; i
< 7; i
++) {
469 p
= getstr(p
, &dtconvp
.abbrev_weekday_names
[i
]);
473 for (i
= 0; i
< 7; i
++) {
474 p
= getstr(p
, &dtconvp
.weekday_names
[i
]);
478 p
= getstr(p
, &dtconvp
.time_format
);
481 p
= getstr(p
, &dtconvp
.sdate_format
);
484 p
= getstr(p
, &dtconvp
.dtime_format
);
487 p
= getstr(p
, &dtconvp
.am_string
);
490 p
= getstr(p
, &dtconvp
.pm_string
);
493 p
= getstr(p
, &dtconvp
.ldate_format
);
501 if (dtconv_str
!= NULL
)
506 /* The following is to get space malloc'd for _dtconv */
509 (void) localdtconv();
510 memcpy(_dtconv
, &dtconvp
, sizeof(struct dtconv
));
528 return (NULL
); /* no end-of-line */