xref: /aosp_15_r20/bionic/libc/tzcode/asctime.c (revision 8d67ca893c1523eb926b9080dbe4e2ffd2a27ba1)
1*8d67ca89SAndroid Build Coastguard Worker /* asctime and asctime_r a la POSIX and ISO C, except pad years before 1000.  */
2*8d67ca89SAndroid Build Coastguard Worker 
3*8d67ca89SAndroid Build Coastguard Worker /*
4*8d67ca89SAndroid Build Coastguard Worker ** This file is in the public domain, so clarified as of
5*8d67ca89SAndroid Build Coastguard Worker ** 1996-06-05 by Arthur David Olson.
6*8d67ca89SAndroid Build Coastguard Worker */
7*8d67ca89SAndroid Build Coastguard Worker 
8*8d67ca89SAndroid Build Coastguard Worker /*
9*8d67ca89SAndroid Build Coastguard Worker ** Avoid the temptation to punt entirely to strftime;
10*8d67ca89SAndroid Build Coastguard Worker ** the output of strftime is supposed to be locale specific
11*8d67ca89SAndroid Build Coastguard Worker ** whereas the output of asctime is supposed to be constant.
12*8d67ca89SAndroid Build Coastguard Worker */
13*8d67ca89SAndroid Build Coastguard Worker 
14*8d67ca89SAndroid Build Coastguard Worker /*LINTLIBRARY*/
15*8d67ca89SAndroid Build Coastguard Worker 
16*8d67ca89SAndroid Build Coastguard Worker #include "private.h"
17*8d67ca89SAndroid Build Coastguard Worker #include <stdio.h>
18*8d67ca89SAndroid Build Coastguard Worker 
19*8d67ca89SAndroid Build Coastguard Worker /*
20*8d67ca89SAndroid Build Coastguard Worker ** All years associated with 32-bit time_t values are exactly four digits long;
21*8d67ca89SAndroid Build Coastguard Worker ** some years associated with 64-bit time_t values are not.
22*8d67ca89SAndroid Build Coastguard Worker ** Vintage programs are coded for years that are always four digits long
23*8d67ca89SAndroid Build Coastguard Worker ** and may assume that the newline always lands in the same place.
24*8d67ca89SAndroid Build Coastguard Worker ** For years that are less than four digits, we pad the output with
25*8d67ca89SAndroid Build Coastguard Worker ** leading zeroes to get the newline in the traditional place.
26*8d67ca89SAndroid Build Coastguard Worker ** The -4 ensures that we get four characters of output even if
27*8d67ca89SAndroid Build Coastguard Worker ** we call a strftime variant that produces fewer characters for some years.
28*8d67ca89SAndroid Build Coastguard Worker ** The ISO C and POSIX standards prohibit padding the year,
29*8d67ca89SAndroid Build Coastguard Worker ** but many implementations pad anyway; most likely the standards are buggy.
30*8d67ca89SAndroid Build Coastguard Worker */
31*8d67ca89SAndroid Build Coastguard Worker static char const ASCTIME_FMT[] = "%s %s%3d %.2d:%.2d:%.2d %-4s\n";
32*8d67ca89SAndroid Build Coastguard Worker /*
33*8d67ca89SAndroid Build Coastguard Worker ** For years that are more than four digits we put extra spaces before the year
34*8d67ca89SAndroid Build Coastguard Worker ** so that code trying to overwrite the newline won't end up overwriting
35*8d67ca89SAndroid Build Coastguard Worker ** a digit within a year and truncating the year (operating on the assumption
36*8d67ca89SAndroid Build Coastguard Worker ** that no output is better than wrong output).
37*8d67ca89SAndroid Build Coastguard Worker */
38*8d67ca89SAndroid Build Coastguard Worker static char const ASCTIME_FMT_B[] = "%s %s%3d %.2d:%.2d:%.2d     %s\n";
39*8d67ca89SAndroid Build Coastguard Worker 
40*8d67ca89SAndroid Build Coastguard Worker enum { STD_ASCTIME_BUF_SIZE = 26 };
41*8d67ca89SAndroid Build Coastguard Worker /*
42*8d67ca89SAndroid Build Coastguard Worker ** Big enough for something such as
43*8d67ca89SAndroid Build Coastguard Worker ** ??? ???-2147483648 -2147483648:-2147483648:-2147483648     -2147483648\n
44*8d67ca89SAndroid Build Coastguard Worker ** (two three-character abbreviations, five strings denoting integers,
45*8d67ca89SAndroid Build Coastguard Worker ** seven explicit spaces, two explicit colons, a newline,
46*8d67ca89SAndroid Build Coastguard Worker ** and a trailing NUL byte).
47*8d67ca89SAndroid Build Coastguard Worker ** The values above are for systems where an int is 32 bits and are provided
48*8d67ca89SAndroid Build Coastguard Worker ** as an example; the size expression below is a bound for the system at
49*8d67ca89SAndroid Build Coastguard Worker ** hand.
50*8d67ca89SAndroid Build Coastguard Worker */
51*8d67ca89SAndroid Build Coastguard Worker static char buf_asctime[2*3 + 5*INT_STRLEN_MAXIMUM(int) + 7 + 2 + 1 + 1];
52*8d67ca89SAndroid Build Coastguard Worker 
53*8d67ca89SAndroid Build Coastguard Worker /* A similar buffer for ctime.
54*8d67ca89SAndroid Build Coastguard Worker    C89 requires that they be the same buffer.
55*8d67ca89SAndroid Build Coastguard Worker    This requirement was removed in C99, so support it only if requested,
56*8d67ca89SAndroid Build Coastguard Worker    as support is more likely to lead to bugs in badly written programs.  */
57*8d67ca89SAndroid Build Coastguard Worker #if SUPPORT_C89
58*8d67ca89SAndroid Build Coastguard Worker # define buf_ctime buf_asctime
59*8d67ca89SAndroid Build Coastguard Worker #else
60*8d67ca89SAndroid Build Coastguard Worker static char buf_ctime[sizeof buf_asctime];
61*8d67ca89SAndroid Build Coastguard Worker #endif
62*8d67ca89SAndroid Build Coastguard Worker 
63*8d67ca89SAndroid Build Coastguard Worker char *
asctime_r(struct tm const * restrict timeptr,char * restrict buf)64*8d67ca89SAndroid Build Coastguard Worker asctime_r(struct tm const *restrict timeptr, char *restrict buf)
65*8d67ca89SAndroid Build Coastguard Worker {
66*8d67ca89SAndroid Build Coastguard Worker 	static const char	wday_name[][4] = {
67*8d67ca89SAndroid Build Coastguard Worker 		"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
68*8d67ca89SAndroid Build Coastguard Worker 	};
69*8d67ca89SAndroid Build Coastguard Worker 	static const char	mon_name[][4] = {
70*8d67ca89SAndroid Build Coastguard Worker 		"Jan", "Feb", "Mar", "Apr", "May", "Jun",
71*8d67ca89SAndroid Build Coastguard Worker 		"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
72*8d67ca89SAndroid Build Coastguard Worker 	};
73*8d67ca89SAndroid Build Coastguard Worker 	register const char *	wn;
74*8d67ca89SAndroid Build Coastguard Worker 	register const char *	mn;
75*8d67ca89SAndroid Build Coastguard Worker 	char			year[INT_STRLEN_MAXIMUM(int) + 2];
76*8d67ca89SAndroid Build Coastguard Worker 	char result[sizeof buf_asctime];
77*8d67ca89SAndroid Build Coastguard Worker 
78*8d67ca89SAndroid Build Coastguard Worker 	if (timeptr == NULL) {
79*8d67ca89SAndroid Build Coastguard Worker 		errno = EINVAL;
80*8d67ca89SAndroid Build Coastguard Worker 		return strcpy(buf, "??? ??? ?? ??:??:?? ????\n");
81*8d67ca89SAndroid Build Coastguard Worker 	}
82*8d67ca89SAndroid Build Coastguard Worker 	if (timeptr->tm_wday < 0 || timeptr->tm_wday >= DAYSPERWEEK)
83*8d67ca89SAndroid Build Coastguard Worker 		wn = "???";
84*8d67ca89SAndroid Build Coastguard Worker 	else	wn = wday_name[timeptr->tm_wday];
85*8d67ca89SAndroid Build Coastguard Worker 	if (timeptr->tm_mon < 0 || timeptr->tm_mon >= MONSPERYEAR)
86*8d67ca89SAndroid Build Coastguard Worker 		mn = "???";
87*8d67ca89SAndroid Build Coastguard Worker 	else	mn = mon_name[timeptr->tm_mon];
88*8d67ca89SAndroid Build Coastguard Worker 	/*
89*8d67ca89SAndroid Build Coastguard Worker 	** Use strftime's %Y to generate the year, to avoid overflow problems
90*8d67ca89SAndroid Build Coastguard Worker 	** when computing timeptr->tm_year + TM_YEAR_BASE.
91*8d67ca89SAndroid Build Coastguard Worker 	** Assume that strftime is unaffected by other out-of-range members
92*8d67ca89SAndroid Build Coastguard Worker 	** (e.g., timeptr->tm_mday) when processing "%Y".
93*8d67ca89SAndroid Build Coastguard Worker 	*/
94*8d67ca89SAndroid Build Coastguard Worker 	strftime(year, sizeof year, "%Y", timeptr);
95*8d67ca89SAndroid Build Coastguard Worker 	/*
96*8d67ca89SAndroid Build Coastguard Worker 	** We avoid using snprintf since it's not available on all systems.
97*8d67ca89SAndroid Build Coastguard Worker 	*/
98*8d67ca89SAndroid Build Coastguard Worker 	snprintf(result, sizeof(result), /* Android change: use snprintf. */
99*8d67ca89SAndroid Build Coastguard Worker 		((strlen(year) <= 4) ? ASCTIME_FMT : ASCTIME_FMT_B),
100*8d67ca89SAndroid Build Coastguard Worker 		wn, mn,
101*8d67ca89SAndroid Build Coastguard Worker 		timeptr->tm_mday, timeptr->tm_hour,
102*8d67ca89SAndroid Build Coastguard Worker 		timeptr->tm_min, timeptr->tm_sec,
103*8d67ca89SAndroid Build Coastguard Worker 		year);
104*8d67ca89SAndroid Build Coastguard Worker 	if (strlen(result) < STD_ASCTIME_BUF_SIZE
105*8d67ca89SAndroid Build Coastguard Worker 	    || buf == buf_ctime || buf == buf_asctime)
106*8d67ca89SAndroid Build Coastguard Worker 		return strcpy(buf, result);
107*8d67ca89SAndroid Build Coastguard Worker 	else {
108*8d67ca89SAndroid Build Coastguard Worker 		errno = EOVERFLOW;
109*8d67ca89SAndroid Build Coastguard Worker 		return NULL;
110*8d67ca89SAndroid Build Coastguard Worker 	}
111*8d67ca89SAndroid Build Coastguard Worker }
112*8d67ca89SAndroid Build Coastguard Worker 
113*8d67ca89SAndroid Build Coastguard Worker char *
asctime(register const struct tm * timeptr)114*8d67ca89SAndroid Build Coastguard Worker asctime(register const struct tm *timeptr)
115*8d67ca89SAndroid Build Coastguard Worker {
116*8d67ca89SAndroid Build Coastguard Worker 	return asctime_r(timeptr, buf_asctime);
117*8d67ca89SAndroid Build Coastguard Worker }
118*8d67ca89SAndroid Build Coastguard Worker 
119*8d67ca89SAndroid Build Coastguard Worker char *
ctime_r(const time_t * timep,char * buf)120*8d67ca89SAndroid Build Coastguard Worker ctime_r(const time_t *timep, char *buf)
121*8d67ca89SAndroid Build Coastguard Worker {
122*8d67ca89SAndroid Build Coastguard Worker   struct tm mytm;
123*8d67ca89SAndroid Build Coastguard Worker   struct tm *tmp = localtime_r(timep, &mytm);
124*8d67ca89SAndroid Build Coastguard Worker   return tmp ? asctime_r(tmp, buf) : NULL;
125*8d67ca89SAndroid Build Coastguard Worker }
126*8d67ca89SAndroid Build Coastguard Worker 
127*8d67ca89SAndroid Build Coastguard Worker char *
ctime(const time_t * timep)128*8d67ca89SAndroid Build Coastguard Worker ctime(const time_t *timep)
129*8d67ca89SAndroid Build Coastguard Worker {
130*8d67ca89SAndroid Build Coastguard Worker   return ctime_r(timep, buf_ctime);
131*8d67ca89SAndroid Build Coastguard Worker }
132