1 /* Extensions for GNU date that are still missing here:
6 /* Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
7 This file is part of the GNU C Library.
9 The GNU C Library is free software; you can redistribute it and/or
10 modify it under the terms of the GNU Library General Public License as
11 published by the Free Software Foundation; either version 2 of the
12 License, or (at your option) any later version.
14 The GNU C Library is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Library General Public License for more details.
19 You should have received a copy of the GNU Library General Public
20 License along with the GNU C Library; see the file COPYING.LIB. If
21 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
22 Cambridge, MA 02139, USA. */
29 # define HAVE_LIMITS_H 1
31 # define HAVE_TM_ZONE 1
32 # define STDC_HEADERS 1
33 # include <ansidecl.h>
34 # include "../locale/localeinfo.h"
38 #include <sys/types.h> /* Some systems define `time_t' here. */
54 # define memcpy(d, s, n) bcopy (s, d, n)
58 #if defined (__GNUC__) || (defined (__STDC__) && __STDC__)
59 #define __P(args) args
73 static unsigned int week __P((const struct tm *const, int));
89 #define cpy(n, s) add((n), memcpy((PTR) p, (PTR) (s), (n)))
92 #define fmt(n, args) add((n), if (sprintf args != (n)) return 0)
94 #define fmt(n, args) add((n), sprintf args; if (strlen (p) != (n)) return 0)
97 /* Return the week in the year specified by TP,
98 with weeks starting on STARTING_DAY. */
103 week (tp, starting_day)
104 const struct tm *const tp;
109 wday = tp->tm_wday - starting_day;
113 /* Set DL to the day in the year of the last day of the week previous to the
114 one containing the day specified in TP. If DL is negative or zero, the
115 day specified in TP is in the first week of the year. Otherwise,
116 calculate the number of complete weeks before our week (DL / 7) and
117 add any partial week at the start of the year (DL % 7). */
118 dl = tp->tm_yday - wday;
119 return dl <= 0 ? 0 : ((dl / 7) + ((dl % 7) == 0 ? 0 : 1));
123 static char const weekday_name[][10] =
125 "Sunday", "Monday", "Tuesday", "Wednesday",
126 "Thursday", "Friday", "Saturday"
128 static char const month_name[][10] =
130 "January", "February", "March", "April", "May", "June",
131 "July", "August", "September", "October", "November", "December"
135 /* Write information from TP into S according to the format
136 string FORMAT, writing no more that MAXSIZE characters
137 (including the terminating '\0') and returning number of
138 characters written. If S is NULL, nothing will be written
139 anywhere, so to determine how many characters would be
140 written, use NULL for S and (size_t) UINT_MAX for MAXSIZE. */
142 strftime (s, maxsize, format, tp)
146 register const struct tm *tp;
148 int hour12 = tp->tm_hour;
150 const char *const a_wkday = _NL_CURRENT (LC_TIME, ABDAY_1 + tp->tm_wday);
151 const char *const f_wkday = _NL_CURRENT (LC_TIME, DAY_1 + tp->tm_wday);
152 const char *const a_month = _NL_CURRENT (LC_TIME, ABMON_1 + tp->tm_mon);
153 const char *const f_month = _NL_CURRENT (LC_TIME, MON_1 + tp->tm_mon);
154 const char *const ampm = _NL_CURRENT (LC_TIME,
155 hour12 > 12 ? PM_STR : AM_STR);
156 size_t aw_len = strlen(a_wkday);
157 size_t am_len = strlen(a_month);
158 size_t ap_len = strlen (ampm);
160 const char *const f_wkday = weekday_name[tp->tm_wday];
161 const char *const f_month = month_name[tp->tm_mon];
162 const char *const a_wkday = f_wkday;
163 const char *const a_month = f_month;
164 const char *const ampm = "AMPM" + 2 * (hour12 > 12);
169 size_t wkday_len = strlen(f_wkday);
170 size_t month_len = strlen(f_month);
171 const unsigned int y_week0 = week (tp, 0);
172 const unsigned int y_week1 = week (tp, 1);
175 register size_t i = 0;
176 register char *p = s;
177 register const char *f;
181 zone = (const char *) tp->tm_zone;
184 if (!(zone && *zone) && tp->tm_isdst >= 0)
185 zone = tzname[tp->tm_isdst];
187 if (!(zone && *zone))
190 zonelen = strlen (zone);
195 if (hour12 == 0) hour12 = 12;
197 for (f = format; *f != '\0'; ++f)
204 /* Non-ASCII, may be a multibyte. */
205 int len = mblen(f, strlen(f));
229 cpy(aw_len, a_wkday);
233 cpy(wkday_len, f_wkday);
237 case 'h': /* GNU extension. */
238 cpy(am_len, a_month);
242 cpy(month_len, f_month);
247 subfmt = _NL_CURRENT (LC_TIME, D_T_FMT);
249 subfmt = "%a %b %d %H:%M:%S %Z %Y";
253 size_t len = strftime (p, maxsize - i, subfmt, tp);
254 if (len == 0 && *subfmt)
261 fmt (2, (p, "%02d", (1900 + tp->tm_year) / 100));
266 subfmt = _NL_CURRENT (LC_TIME, D_FMT);
270 case 'D': /* GNU extension. */
275 fmt(2, (p, "%02d", tp->tm_mday));
278 case 'e': /* GNU extension: %d, but blank-padded. */
279 fmt(2, (p, "%2d", tp->tm_mday));
283 fmt(2, (p, "%02d", tp->tm_hour));
287 fmt(2, (p, "%02d", hour12));
290 case 'k': /* GNU extension. */
291 fmt(2, (p, "%2d", tp->tm_hour));
294 case 'l': /* GNU extension. */
295 fmt(2, (p, "%2d", hour12));
299 fmt(3, (p, "%03d", 1 + tp->tm_yday));
303 fmt(2, (p, "%02d", tp->tm_min));
307 fmt(2, (p, "%02d", tp->tm_mon + 1));
310 case 'n': /* GNU extension. */
318 case 'R': /* GNU extension. */
322 case 'r': /* GNU extension. */
323 subfmt = "%I:%M:%S %p";
327 fmt(2, (p, "%02d", tp->tm_sec));
332 subfmt = _NL_CURRENT (LC_TIME, T_FMT);
336 case 'T': /* GNU extenstion. */
340 case 't': /* GNU extenstion. */
345 fmt(2, (p, "%02u", y_week0));
349 fmt(2, (p, "%02u", y_week1));
353 fmt(2, (p, "%02d", tp->tm_wday));
357 fmt(4, (p, "%04d", 1900 + tp->tm_year));
361 fmt(2, (p, "%02d", tp->tm_year % 100));