2 static char *RCSid() { return RCSid("$Id: strftime.c,v 1.7 2004/07/01 17:10:08 broeker Exp $"); }
5 /* GNUPLOT - strftime.c */
8 * Copyright 1986 - 1993, 1998, 2004 Thomas Williams, Colin Kelley
10 * Permission to use, copy, and distribute this software and its
11 * documentation for any purpose with or without fee is hereby granted,
12 * provided that the above copyright notice appear in all copies and
13 * that both that copyright notice and this permission notice appear
14 * in supporting documentation.
16 * Permission to modify the software is granted, but not the right to
17 * distribute the complete modified source code. Modifications are to
18 * be distributed as patches to the released version. Permission to
19 * distribute binaries produced by compiling modified sources is granted,
21 * 1. distribute the corresponding source modifications from the
22 * released version in the form of a patch file along with the binaries,
23 * 2. add special version identification to distinguish your version
24 * in addition to the base release version number,
25 * 3. provide your name and address as the primary contact for the
26 * support of your modified version, and
27 * 4. retain our contact information in regard to use of the base
29 * Permission to distribute the released version of the source code along
30 * with corresponding source modifications in the form of a patch file is
31 * granted with same provisions 2 through 4 for binary distributions.
33 * This software is provided "as is" without express or implied warranty
34 * to the extent permitted by applicable law.
38 * Implementation of strftime for systems missing this (e.g. vaxctrl)
40 * This code was written based on the NeXT strftime man-page, sample output of
41 * the function and an ANSI-C quickreference chart. This code does not use
42 * parts of any existing strftime implementation.
44 * Apparently not all format chars are implemented, but this was all I had in
47 * (written by Alexander Lehmann)
52 #include "syscfg.h" /* for MAX_LINE_LEN */
53 #include "stdfn.h" /* for safe_strncpy */
55 #ifdef TEST_STRFTIME /* test case; link with stdfn */
56 #define strftime _strftime
59 #include "national.h" /* language info for the following, */
60 /* extracted from set.c */
62 char full_month_names[12][32] =
63 {FMON01, FMON02, FMON03, FMON04, FMON05,
64 FMON06, FMON07, FMON08, FMON09, FMON10, FMON11, FMON12};
65 char abbrev_month_names[12][8] =
66 {AMON01, AMON02, AMON03, AMON04, AMON05,
67 AMON06, AMON07, AMON08, AMON09, AMON10, AMON11, AMON12};
69 char full_day_names[7][32] =
70 {FDAY0, FDAY1, FDAY2, FDAY3, FDAY4, FDAY5, FDAY6};
71 char abbrev_day_names[7][8] =
72 {ADAY0, ADAY1, ADAY2, ADAY3, ADAY4, ADAY5, ADAY6};
74 #endif /* TEST_STRFTIME */
76 static void fill __PROTO((char *from, char **pto, size_t *pmaxsize));
77 static void number __PROTO((int num, int pad, char **pto, size_t *pmaxsize));
80 fill(char *from, char **pto, size_t *pmaxsize)
82 safe_strncpy(*pto, from, *pmaxsize);
83 if (*pmaxsize < strlen(from)) {
87 (*pto) += strlen(from);
88 (*pmaxsize) -= strlen(from);
93 number(int num, int pad, char **pto, size_t *pmaxsize)
97 sprintf(str, "%0*d", pad, num);
98 fill(str, pto, pmaxsize);
102 strftime(char *s, size_t max, const char *format, const struct tm *tp)
105 size_t maxsize = max;
108 while (*format && max > 0) {
109 if (*format != '%') {
115 case 'a': /* abbreviated weekday name */
116 if (tp->tm_wday >= 0 && tp->tm_wday <= 6)
117 fill(abbrev_day_names[tp->tm_wday], &s, &max);
119 case 'A': /* full name of the weekday */
120 if (tp->tm_wday >= 0 && tp->tm_wday <= 6)
121 fill(full_day_names[tp->tm_wday], &s, &max);
123 case 'b': /* abbreviated month name */
124 if (tp->tm_mon >= 0 && tp->tm_mon <= 11)
125 fill(abbrev_month_names[tp->tm_mon], &s, &max);
127 case 'B': /* full name of month */
128 if (tp->tm_mon >= 0 && tp->tm_mon <= 11)
129 fill(full_month_names[tp->tm_mon], &s, &max);
131 case 'c': /* locale's date and time reprensentation */
132 strftime(s, max, "%a %b %X %Y", tp);
136 case 'd': /* day of the month (01-31) */
137 number(tp->tm_mday, 2, &s, &max);
139 case 'H': /* hour of the day (00-23) */
140 number(tp->tm_hour, 2, &s, &max);
142 case 'I': /* hour of the day (01-12) */
143 number((tp->tm_hour + 11) % 12 + 1, 2, &s, &max);
145 case 'j': /* day of the year (001-366) */
146 number(tp->tm_yday + 1, 3, &s, &max);
148 case 'm': /* month of the year (01-12) */
149 number(tp->tm_mon + 1, 2, &s, &max);
151 case 'M': /* minute (00-59) */
152 number(tp->tm_min, 2, &s, &max);
154 case 'p': /* locale's version of AM or PM */
155 fill(tp->tm_hour >= 6 ? "PM" : "AM", &s, &max);
157 case 'S': /* seconds (00-59) */
158 number(tp->tm_sec, 2, &s, &max);
160 case 'U': /* week number of the year (00-53) with Sunday as the first day of the week */
161 number((tp->tm_yday - (tp->tm_yday - tp->tm_wday + 7) % 7 + 7) / 7, 1, &s, &max);
163 case 'w': /* weekday (Sunday = 0 to Saturday = 6) */
164 number(tp->tm_wday, 1, &s, &max);
166 case 'W': /* week number of the year (00-53) with Monday as the first day of the week */
167 number((tp->tm_yday - (tp->tm_yday - tp->tm_wday + 8) % 7 + 7) / 7, 2, &s, &max);
169 case 'x': /* locale's date representation */
170 strftime(s, max, "%a %b %d %Y", tp);
174 case 'X': /* locale's time representation */
176 strftime(s, max, "%H:%M:%S %Z", tp);
178 strftime(s, max, "%H:%M:%S", tp);
183 case 'y': /* two-digit year representation (00-99) */
184 number(tp->tm_year % 100, 2, &s, &max);
186 case 'Y': /* four-digit year representation */
187 number(tp->tm_year + 1900, 2, &s, &max);
190 case 'Z': /* time zone name */
191 fill(tp->tm_zone, &s, &max);
194 case '%': /* percent sign */
196 *s++ = *(format - 1);
202 if (s - start < maxsize) {
215 printf("%s -> ",s ); \
216 _strftime(str, 100, s, ts); \
217 printf("%s - ", str); \
218 strftime(str, 100, s, ts); \
235 test("%a %b %d %X %Y");
238 test("%I:%M %p %j %w");
240 t -= 245 * 24 * 60 * 60;
242 for (i = 0; i < 366; i++) {