Mercurial > hg > xemacs-beta
annotate src/strftime.c @ 5538:580ef98f2beb
Suppress a "shadowed global" warning.
The warning is for j1 from <math.h> on Darwin.
| author | Stephen J. Turnbull <stephen@xemacs.org> |
|---|---|
| date | Mon, 08 Aug 2011 13:57:18 +0900 |
| parents | 308d34e9f07d |
| children |
| rev | line source |
|---|---|
| 428 | 1 /* strftime - custom formatting of date and/or time |
| 2 Copyright (C) 1989, 1991, 1992 Free Software Foundation, Inc. | |
| 3 | |
|
5402
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
5254
diff
changeset
|
4 This file is part of XEmacs. |
|
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
5254
diff
changeset
|
5 |
|
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
5254
diff
changeset
|
6 XEmacs is free software: you can redistribute it and/or modify it |
|
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
5254
diff
changeset
|
7 under the terms of the GNU General Public License as published by the |
|
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
5254
diff
changeset
|
8 Free Software Foundation, either version 3 of the License, or (at your |
|
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
5254
diff
changeset
|
9 option) any later version. |
|
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
5254
diff
changeset
|
10 |
|
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
5254
diff
changeset
|
11 XEmacs is distributed in the hope that it will be useful, but WITHOUT |
|
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
5254
diff
changeset
|
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
5254
diff
changeset
|
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
5254
diff
changeset
|
14 for more details. |
|
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
5254
diff
changeset
|
15 |
| 428 | 16 You should have received a copy of the GNU General Public License |
|
5402
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
5254
diff
changeset
|
17 along with XEmacs. If not, see <http://www.gnu.org/licenses/>. */ |
| 428 | 18 /* Synched up with: FSF 19.30. */ |
| 19 | |
| 771 | 20 /* This file has been ... uhhhhh ... Mule-ized. Yeah. |
| 21 | |
| 22 (Everything here is external format. This is DANGEROUS and | |
| 23 data-lossy, but fixing it is too much of a bother now.) --ben */ | |
| 24 | |
| 428 | 25 /* Note: this version of strftime lacks locale support, |
| 26 but it is standalone. | |
| 27 | |
| 28 Performs `%' substitutions similar to those in printf. Except | |
| 29 where noted, substituted fields have a fixed size; numeric fields are | |
| 30 padded if necessary. Padding is with zeros by default; for fields | |
| 31 that display a single number, padding can be changed or inhibited by | |
| 32 following the `%' with one of the modifiers described below. Unknown | |
| 33 field specifiers are copied as normal characters. All other | |
| 34 characters are copied to the output without change. | |
| 35 | |
| 36 Supports a superset of the ANSI C field specifiers. | |
| 37 | |
| 38 Literal character fields: | |
| 39 % % | |
| 40 n newline | |
| 41 t tab | |
| 42 | |
| 43 Numeric modifiers (a nonstandard extension): | |
| 44 - do not pad the field | |
| 45 _ pad the field with spaces | |
| 46 | |
| 47 Time fields: | |
| 48 %H hour (00..23) | |
| 49 %I hour (01..12) | |
| 50 %k hour ( 0..23) | |
| 51 %l hour ( 1..12) | |
| 52 %M minute (00..59) | |
| 53 %p locale's AM or PM | |
| 54 %r time, 12-hour (hh:mm:ss [AP]M) | |
| 55 %R time, 24-hour (hh:mm) | |
| 56 %s time in seconds since 00:00:00, Jan 1, 1970 (a nonstandard extension) | |
| 57 %S second (00..61) | |
| 58 %T time, 24-hour (hh:mm:ss) | |
| 59 %X locale's time representation (%H:%M:%S) | |
| 4203 | 60 %z time zone offset (e.g. +0530, -0800 etc) |
| 428 | 61 %Z time zone (EDT), or nothing if no time zone is determinable |
| 62 | |
| 63 Date fields: | |
| 64 %a locale's abbreviated weekday name (Sun..Sat) | |
| 65 %A locale's full weekday name, variable length (Sunday..Saturday) | |
| 66 %b locale's abbreviated month name (Jan..Dec) | |
| 67 %B locale's full month name, variable length (January..December) | |
| 68 %c locale's date and time (Sat Nov 04 12:02:33 EST 1989) | |
| 69 %C century (00..99) | |
| 70 %d day of month (01..31) | |
| 71 %e day of month ( 1..31) | |
| 72 %D date (mm/dd/yy) | |
| 4203 | 73 %G year corresponding to the ISO 8601 week |
| 74 %g Year of the ISO 8601 week within century (00 - 99) | |
| 428 | 75 %h same as %b |
| 76 %j day of year (001..366) | |
| 77 %m month (01..12) | |
| 78 %U week number of year with Sunday as first day of week (00..53) | |
| 4203 | 79 %V ISO 8601 week number (first week is the earliest one with Thu) |
| 428 | 80 %w day of week (0..6) |
| 81 %W week number of year with Monday as first day of week (00..53) | |
| 82 %x locale's date representation (mm/dd/yy) | |
| 83 %y last two digits of year (00..99) | |
| 84 %Y year (1970...) | |
| 85 | |
| 86 David MacKenzie <djm@gnu.ai.mit.edu> */ | |
| 87 | |
| 88 #ifdef HAVE_CONFIG_H | |
| 89 #include <config.h> | |
| 90 #include "lisp.h" | |
| 91 #endif | |
| 92 | |
| 93 #include <stdio.h> | |
| 94 #include <sys/types.h> | |
| 95 #if defined(TM_IN_SYS_TIME) || (!defined(HAVE_TM_ZONE) && !defined(HAVE_TZNAME)) | |
| 96 #include <sys/time.h> | |
| 97 #else | |
| 98 #include <time.h> | |
| 99 #endif | |
| 100 | |
| 101 #ifndef STDC_HEADERS | |
| 102 time_t mktime (); | |
| 103 #endif | |
| 104 | |
| 442 | 105 #if defined(WIN32_NATIVE) || defined(CYGWIN) |
| 428 | 106 #include <time.h> |
| 107 #else | |
| 108 #if defined(HAVE_TZNAME) | |
| 109 extern char *tzname[2]; | |
| 110 #endif | |
| 442 | 111 #endif /* WIN32_NATIVE */ |
| 428 | 112 |
| 113 #ifdef emacs | |
| 114 #define strftime emacs_strftime | |
| 115 #endif | |
| 116 | |
| 117 /* Types of padding for numbers in date and time. */ | |
| 118 enum padding | |
| 119 { | |
| 120 none, blank, zero | |
| 121 }; | |
| 122 | |
| 442 | 123 static char const* const days[] = |
| 428 | 124 { |
| 125 "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" | |
| 126 }; | |
| 127 | |
| 442 | 128 static char const * const months[] = |
| 428 | 129 { |
| 130 "January", "February", "March", "April", "May", "June", | |
| 131 "July", "August", "September", "October", "November", "December" | |
| 132 }; | |
| 133 | |
|
5254
1537701f08a1
Support Roman month numbers, #'format-time-string
Aidan Kehoe <kehoea@parhasard.net>
parents:
5016
diff
changeset
|
134 static char const * const roman_upper[] = |
|
1537701f08a1
Support Roman month numbers, #'format-time-string
Aidan Kehoe <kehoea@parhasard.net>
parents:
5016
diff
changeset
|
135 { |
|
1537701f08a1
Support Roman month numbers, #'format-time-string
Aidan Kehoe <kehoea@parhasard.net>
parents:
5016
diff
changeset
|
136 "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X", "XI", "XII" |
|
1537701f08a1
Support Roman month numbers, #'format-time-string
Aidan Kehoe <kehoea@parhasard.net>
parents:
5016
diff
changeset
|
137 }; |
|
1537701f08a1
Support Roman month numbers, #'format-time-string
Aidan Kehoe <kehoea@parhasard.net>
parents:
5016
diff
changeset
|
138 |
|
1537701f08a1
Support Roman month numbers, #'format-time-string
Aidan Kehoe <kehoea@parhasard.net>
parents:
5016
diff
changeset
|
139 static char const * const roman_lower[] = |
|
1537701f08a1
Support Roman month numbers, #'format-time-string
Aidan Kehoe <kehoea@parhasard.net>
parents:
5016
diff
changeset
|
140 { |
|
1537701f08a1
Support Roman month numbers, #'format-time-string
Aidan Kehoe <kehoea@parhasard.net>
parents:
5016
diff
changeset
|
141 "i", "ii", "iii", "iv", "v", "vi", "vii", "viii", "ix", "x", "xi", "xii" |
|
1537701f08a1
Support Roman month numbers, #'format-time-string
Aidan Kehoe <kehoea@parhasard.net>
parents:
5016
diff
changeset
|
142 }; |
|
1537701f08a1
Support Roman month numbers, #'format-time-string
Aidan Kehoe <kehoea@parhasard.net>
parents:
5016
diff
changeset
|
143 |
| 428 | 144 /* Add character C to STRING and increment LENGTH, |
| 145 unless LENGTH would exceed MAX. */ | |
| 146 | |
| 147 #define add_char(c) do \ | |
| 148 { \ | |
| 149 if (length + 1 <= max) \ | |
| 150 string[length++] = (c); \ | |
| 151 } while (0) | |
| 152 | |
| 153 /* Add a 2 digit number to STRING, padding if specified. | |
| 154 Return the number of characters added, up to MAX. */ | |
| 155 | |
| 156 static int | |
| 157 add_num2 (char *string, int num, int max, enum padding pad) | |
| 158 { | |
| 159 int top = num / 10; | |
| 160 int length = 0; | |
| 161 | |
| 162 if (top == 0 && pad == blank) | |
| 163 add_char (' '); | |
| 164 else if (top != 0 || pad == zero) | |
| 165 add_char (top + '0'); | |
| 166 add_char (num % 10 + '0'); | |
| 167 return length; | |
| 168 } | |
| 169 | |
| 170 /* Add a 3 digit number to STRING, padding if specified. | |
| 171 Return the number of characters added, up to MAX. */ | |
| 172 | |
| 173 static int | |
| 174 add_num3 (char *string, int num, int max, enum padding pad) | |
| 175 { | |
| 176 int top = num / 100; | |
| 177 int mid = (num - top * 100) / 10; | |
| 178 int length = 0; | |
| 179 | |
| 180 if (top == 0 && pad == blank) | |
| 181 add_char (' '); | |
| 182 else if (top != 0 || pad == zero) | |
| 183 add_char (top + '0'); | |
| 184 if (mid == 0 && top == 0 && pad == blank) | |
| 185 add_char (' '); | |
| 186 else if (mid != 0 || top != 0 || pad == zero) | |
| 187 add_char (mid + '0'); | |
| 188 add_char (num % 10 + '0'); | |
| 189 return length; | |
| 190 } | |
| 191 | |
| 192 /* Like strncpy except return the number of characters copied. */ | |
| 193 | |
| 194 static int | |
| 442 | 195 add_str (char *to, const char *from, int max) |
| 428 | 196 { |
| 197 int i; | |
| 198 | |
| 199 for (i = 0; from[i] && i <= max; ++i) | |
| 200 to[i] = from[i]; | |
| 201 return i; | |
| 202 } | |
| 203 | |
| 204 static int | |
| 205 add_num_time_t (char *string, int max, time_t num) | |
| 206 { | |
| 207 /* This buffer is large enough to hold the character representation | |
| 208 (including the trailing NUL) of any unsigned decimal quantity | |
| 209 whose binary representation fits in 128 bits. */ | |
| 210 char buf[40]; | |
| 211 | |
| 212 if (sizeof (num) > 16) | |
| 2500 | 213 ABORT (); |
| 428 | 214 sprintf (buf, "%lu", (unsigned long) num); |
| 793 | 215 return add_str (string, buf, max); |
| 428 | 216 } |
| 217 | |
| 218 /* Return the week in the year of the time in TM, with the weeks | |
| 219 starting on Sundays. */ | |
| 220 | |
| 221 static int | |
| 442 | 222 sun_week (const struct tm *tm) |
| 428 | 223 { |
| 224 int dl; | |
| 225 | |
| 226 /* Set `dl' to the day in the year of the last day of the week previous | |
| 227 to the one containing the day specified in TM. If the day specified | |
| 228 in TM is in the first week of the year, `dl' will be negative or 0. | |
| 229 Otherwise, calculate the number of complete weeks before our week | |
| 230 (dl / 7) and add any partial week at the start of the year (dl % 7). */ | |
| 231 dl = tm->tm_yday - tm->tm_wday; | |
| 232 return dl <= 0 ? 0 : dl / 7 + (dl % 7 != 0); | |
| 233 } | |
| 234 | |
| 235 /* Return the week in the year of the time in TM, with the weeks | |
| 236 starting on Mondays. */ | |
| 237 | |
| 238 static int | |
| 442 | 239 mon_week (const struct tm *tm) |
| 428 | 240 { |
| 241 int dl, wday; | |
| 242 | |
| 243 if (tm->tm_wday == 0) | |
| 244 wday = 6; | |
| 245 else | |
| 246 wday = tm->tm_wday - 1; | |
| 247 dl = tm->tm_yday - wday; | |
| 248 return dl <= 0 ? 0 : dl / 7 + (dl % 7 != 0); | |
| 249 } | |
| 250 | |
| 4203 | 251 #ifndef __isleap |
| 252 /* Nonzero if YEAR is a leap year (every 4 years, | |
| 253 except every 100th isn't, and every 400th is). */ | |
| 254 # define __isleap(year) \ | |
| 255 ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0)) | |
| 256 #endif | |
| 257 | |
| 258 /* The number of days from the first day of the first ISO week of this | |
| 259 year to the year day YDAY with week day WDAY. ISO weeks start on | |
| 260 Monday; the first ISO week has the year's first Thursday. YDAY may | |
| 261 be as small as YDAY_MINIMUM. */ | |
| 262 #define ISO_WEEK_START_WDAY 1 /* Monday */ | |
| 263 #define ISO_WEEK1_WDAY 4 /* Thursday */ | |
| 264 #define YDAY_MINIMUM (-366) | |
| 265 static int | |
| 266 iso_week_days (int yday, int wday) | |
| 267 { | |
| 268 /* Add enough to the first operand of % to make it nonnegative. */ | |
| 269 int big_enough_multiple_of_7 = (-YDAY_MINIMUM / 7 + 2) * 7; | |
| 270 return (yday | |
| 271 - (yday - wday + ISO_WEEK1_WDAY + big_enough_multiple_of_7) % 7 | |
| 272 + ISO_WEEK1_WDAY - ISO_WEEK_START_WDAY); | |
| 273 } | |
| 274 | |
| 428 | 275 #if !defined(HAVE_TM_ZONE) && !defined(HAVE_TZNAME) |
| 442 | 276 char *zone_name (const struct tm *tp); |
| 428 | 277 char * |
| 442 | 278 zone_name (const struct tm *tp) |
| 428 | 279 { |
| 280 char *timezone (); | |
| 281 struct timeval tv; | |
| 282 struct timezone tz; | |
| 283 | |
| 284 gettimeofday (&tv, &tz); | |
| 285 return timezone (tz.tz_minuteswest, tp->tm_isdst); | |
| 286 } | |
| 287 #endif | |
| 288 | |
| 289 /* Format the time given in TM according to FORMAT, and put the | |
| 290 results in STRING. | |
| 291 Return the number of characters (not including terminating null) | |
| 292 that were put into STRING, or 0 if the length would have | |
| 293 exceeded MAX. */ | |
| 294 | |
| 442 | 295 size_t strftime (char *string, size_t max, const char *format, |
| 296 const struct tm *tm); | |
| 428 | 297 |
| 298 size_t | |
| 442 | 299 strftime (char *string, size_t max, const char *format, const struct tm *tm) |
| 428 | 300 { |
| 301 enum padding pad; /* Type of padding to apply. */ | |
| 302 size_t length = 0; /* Characters put in STRING so far. */ | |
| 303 | |
| 304 for (; *format && length < max; ++format) | |
| 305 { | |
| 306 if (*format != '%') | |
| 307 add_char (*format); | |
| 308 else | |
| 309 { | |
| 310 ++format; | |
| 311 /* Modifiers: */ | |
| 312 if (*format == '-') | |
| 313 { | |
| 314 pad = none; | |
| 315 ++format; | |
| 316 } | |
| 317 else if (*format == '_') | |
| 318 { | |
| 319 pad = blank; | |
| 320 ++format; | |
| 321 } | |
| 322 else | |
| 323 pad = zero; | |
| 324 | |
| 325 switch (*format) | |
| 326 { | |
| 327 /* Literal character fields: */ | |
| 328 case 0: | |
| 329 case '%': | |
| 330 add_char ('%'); | |
| 331 break; | |
| 332 case 'n': | |
| 333 add_char ('\n'); | |
| 334 break; | |
| 335 case 't': | |
| 336 add_char ('\t'); | |
| 337 break; | |
| 338 default: | |
| 339 add_char (*format); | |
| 340 break; | |
| 341 | |
| 342 /* Time fields: */ | |
| 343 case 'H': | |
| 344 case 'k': | |
| 345 length += | |
| 346 add_num2 (&string[length], tm->tm_hour, max - length, | |
| 347 *format == 'H' ? pad : blank); | |
| 348 break; | |
| 349 case 'I': | |
| 350 case 'l': | |
| 351 { | |
| 352 int hour12; | |
| 353 | |
| 354 if (tm->tm_hour == 0) | |
| 355 hour12 = 12; | |
| 356 else if (tm->tm_hour > 12) | |
| 357 hour12 = tm->tm_hour - 12; | |
| 358 else | |
| 359 hour12 = tm->tm_hour; | |
| 360 length += | |
| 361 add_num2 (&string[length], hour12, max - length, | |
| 362 *format == 'I' ? pad : blank); | |
| 363 } | |
| 364 break; | |
| 365 case 'M': | |
| 366 length += | |
| 367 add_num2 (&string[length], tm->tm_min, max - length, pad); | |
| 368 break; | |
| 369 case 'p': | |
| 370 if (tm->tm_hour < 12) | |
| 371 add_char ('A'); | |
| 372 else | |
| 373 add_char ('P'); | |
| 374 add_char ('M'); | |
| 375 break; | |
| 376 case 'r': | |
| 377 length += | |
| 378 strftime (&string[length], max - length, "%I:%M:%S %p", tm); | |
| 379 break; | |
| 380 case 'R': | |
| 381 length += | |
| 382 strftime (&string[length], max - length, "%H:%M", tm); | |
| 383 break; | |
| 384 | |
| 385 case 's': | |
| 386 { | |
| 387 struct tm writable_tm; | |
| 388 writable_tm = *tm; | |
| 389 length += add_num_time_t (&string[length], max - length, | |
| 390 mktime (&writable_tm)); | |
| 391 } | |
| 392 break; | |
| 393 | |
| 394 case 'S': | |
| 395 length += | |
| 396 add_num2 (&string[length], tm->tm_sec, max - length, pad); | |
| 397 break; | |
| 398 case 'T': | |
| 399 length += | |
| 400 strftime (&string[length], max - length, "%H:%M:%S", tm); | |
| 401 break; | |
| 4203 | 402 |
| 403 case 'V': | |
| 404 case 'g': | |
| 405 case 'G': | |
| 406 { | |
| 407 int year = tm->tm_year + 1900; | |
|
5016
2ade80e8c640
enable more warnings and fix them
Ben Wing <ben@xemacs.org>
parents:
4203
diff
changeset
|
408 int ndays = iso_week_days (tm->tm_yday, tm->tm_wday); |
| 4203 | 409 |
|
5016
2ade80e8c640
enable more warnings and fix them
Ben Wing <ben@xemacs.org>
parents:
4203
diff
changeset
|
410 if (ndays < 0) |
| 4203 | 411 { |
| 412 /* This ISO week belongs to the previous year. */ | |
| 413 year--; | |
|
5016
2ade80e8c640
enable more warnings and fix them
Ben Wing <ben@xemacs.org>
parents:
4203
diff
changeset
|
414 ndays = |
| 4203 | 415 iso_week_days (tm->tm_yday + (365 + __isleap (year)), |
| 416 tm->tm_wday); | |
| 417 } | |
| 418 else | |
| 419 { | |
| 420 int d = | |
| 421 iso_week_days (tm->tm_yday - (365 + __isleap (year)), | |
| 422 tm->tm_wday); | |
| 423 if (0 <= d) | |
| 424 { | |
| 425 /* This ISO week belongs to the next year. */ | |
| 426 year++; | |
|
5016
2ade80e8c640
enable more warnings and fix them
Ben Wing <ben@xemacs.org>
parents:
4203
diff
changeset
|
427 ndays = d; |
| 4203 | 428 } |
| 429 } | |
| 430 | |
| 431 switch (*format) | |
| 432 { | |
| 433 /* | |
| 434 #### FIXME | |
| 435 We really can't assume 1000 <= year <= 9999 | |
| 436 once time_t gets beyond 32 bits, but it's true | |
| 437 of the rest of the code here so get with the | |
| 438 program | |
| 439 */ | |
| 440 case 'g': | |
| 441 length += | |
| 442 add_num2 (&string[length], year % 100, | |
| 443 max - length, pad); | |
| 444 break; | |
| 445 | |
| 446 case 'G': | |
| 447 add_char (year / 1000 + '0'); | |
| 448 length += add_num3 (&string[length], year % 1000, | |
| 449 max - length, zero); | |
| 450 break; | |
| 451 | |
| 452 default: | |
| 453 length += | |
|
5016
2ade80e8c640
enable more warnings and fix them
Ben Wing <ben@xemacs.org>
parents:
4203
diff
changeset
|
454 add_num2 (&string[length], ndays / 7 + 1, |
| 4203 | 455 max - length, pad); |
| 456 break; | |
| 457 } | |
| 458 } | |
| 459 break; | |
| 428 | 460 case 'X': |
| 461 length += | |
| 462 strftime (&string[length], max - length, "%H:%M:%S", tm); | |
| 463 break; | |
| 4203 | 464 case 'z': |
| 465 { | |
| 466 /* | |
| 467 #### FIXME: could use tm->tm_gmtoff if present. Since | |
| 468 the other code in xemacs does not do so we follow the | |
| 469 leaders (and don't add a autoconf macro to detect | |
| 470 its presence). | |
| 471 */ | |
| 472 long int offset; | |
| 473 long int minutes; | |
| 474 struct tm lt, *ut; | |
| 475 time_t utc; | |
| 476 | |
| 477 lt = *tm; | |
| 478 utc = mktime(<); | |
| 479 ut = gmtime(&utc); | |
| 480 /* assume that tm is valid so the others will be too! */ | |
| 481 assert( utc != (time_t) -1 && ut != NULL ); | |
| 482 | |
| 483 /* tm diff code below is based on mktime.c, glibc 2.3.2 */ | |
| 484 { | |
| 485 int lt4, ut4, lt100, ut100, lt400, ut400; | |
|
5016
2ade80e8c640
enable more warnings and fix them
Ben Wing <ben@xemacs.org>
parents:
4203
diff
changeset
|
486 int intervening_leap_days, years, ndays; |
| 4203 | 487 |
| 488 lt4 = (lt.tm_year >> 2) + (1900 >> 2) - | |
| 489 ! (lt.tm_year & 3); | |
| 490 ut4 = (ut->tm_year >> 2) + (1900 >> 2) - | |
| 491 ! (ut->tm_year & 3); | |
| 492 lt100 = lt4 / 25 - (lt4 % 25 < 0); | |
| 493 ut100 = ut4 / 25 - (ut4 % 25 < 0); | |
| 494 lt400 = lt100 >> 2; | |
| 495 ut400 = ut100 >> 2; | |
| 496 intervening_leap_days = | |
| 497 (lt4 - ut4) - (lt100 - ut100) + (lt400 - ut400); | |
| 498 years = lt.tm_year - ut->tm_year; | |
|
5016
2ade80e8c640
enable more warnings and fix them
Ben Wing <ben@xemacs.org>
parents:
4203
diff
changeset
|
499 ndays = (365 * years + intervening_leap_days |
| 4203 | 500 + (lt.tm_yday - ut->tm_yday)); |
|
5016
2ade80e8c640
enable more warnings and fix them
Ben Wing <ben@xemacs.org>
parents:
4203
diff
changeset
|
501 offset = (60 * (60 * (24 * ndays |
|
2ade80e8c640
enable more warnings and fix them
Ben Wing <ben@xemacs.org>
parents:
4203
diff
changeset
|
502 + (lt.tm_hour - ut->tm_hour)) |
| 4203 | 503 + (lt.tm_min - ut->tm_min)) |
| 504 + (lt.tm_sec - ut->tm_sec)); | |
| 505 } | |
| 506 | |
| 507 minutes = offset / ( offset < 0 ? -60 : 60 ); | |
| 508 | |
| 509 add_char ((offset < 0 ? '-' : '+')); | |
| 510 | |
| 511 if ( minutes / 600 != 0 ) | |
| 512 add_char (minutes / 600 + '0'); | |
| 513 else if ( pad != none ) | |
| 514 add_char ((pad == zero ? '0' : ' ')); | |
| 515 | |
| 516 length += | |
| 517 add_num3 (&string[length], | |
| 518 ((minutes / 60 ) % 10) * 100 + (minutes % 60), | |
| 519 max - length, pad); | |
| 520 break; | |
| 521 } | |
| 428 | 522 case 'Z': |
| 523 #ifdef HAVE_TM_ZONE | |
| 524 length += add_str (&string[length], tm->tm_zone, max - length); | |
| 525 #else | |
| 526 #ifdef HAVE_TZNAME | |
| 527 if (tm->tm_isdst && tzname[1] && *tzname[1]) | |
| 528 length += add_str (&string[length], tzname[1], max - length); | |
| 529 else | |
| 530 length += add_str (&string[length], tzname[0], max - length); | |
| 531 #else | |
| 532 length += add_str (&string[length], zone_name (tm), max - length); | |
| 533 #endif | |
| 534 #endif | |
| 535 break; | |
| 536 | |
| 537 /* Date fields: */ | |
| 538 case 'a': | |
| 539 add_char (days[tm->tm_wday][0]); | |
| 540 add_char (days[tm->tm_wday][1]); | |
| 541 add_char (days[tm->tm_wday][2]); | |
| 542 break; | |
| 543 case 'A': | |
| 544 length += | |
| 545 add_str (&string[length], days[tm->tm_wday], max - length); | |
| 546 break; | |
| 547 case 'b': | |
| 548 case 'h': | |
| 549 add_char (months[tm->tm_mon][0]); | |
| 550 add_char (months[tm->tm_mon][1]); | |
| 551 add_char (months[tm->tm_mon][2]); | |
| 552 break; | |
| 553 case 'B': | |
| 554 length += | |
| 555 add_str (&string[length], months[tm->tm_mon], max - length); | |
| 556 break; | |
| 557 case 'c': | |
| 558 length += | |
| 559 strftime (&string[length], max - length, | |
| 560 "%a %b %d %H:%M:%S %Z %Y", tm); | |
| 561 break; | |
| 562 case 'C': | |
| 563 length += | |
| 564 add_num2 (&string[length], (tm->tm_year + 1900) / 100, | |
| 565 max - length, pad); | |
| 566 break; | |
| 567 case 'd': | |
| 568 length += | |
| 569 add_num2 (&string[length], tm->tm_mday, max - length, pad); | |
| 570 break; | |
| 571 case 'e': | |
| 572 length += | |
| 573 add_num2 (&string[length], tm->tm_mday, max - length, blank); | |
| 574 break; | |
| 575 case 'D': | |
| 576 length += | |
| 577 strftime (&string[length], max - length, "%m/%d/%y", tm); | |
| 578 break; | |
| 579 case 'j': | |
| 580 length += | |
| 581 add_num3 (&string[length], tm->tm_yday + 1, max - length, pad); | |
| 582 break; | |
| 583 case 'm': | |
| 584 length += | |
| 585 add_num2 (&string[length], tm->tm_mon + 1, max - length, pad); | |
| 586 break; | |
| 587 case 'U': | |
| 588 length += | |
| 589 add_num2 (&string[length], sun_week (tm), max - length, pad); | |
| 590 break; | |
| 591 case 'w': | |
| 592 add_char (tm->tm_wday + '0'); | |
| 593 break; | |
| 594 case 'W': | |
| 595 length += | |
| 596 add_num2 (&string[length], mon_week (tm), max - length, pad); | |
| 597 break; | |
| 598 case 'x': | |
| 599 length += | |
| 600 strftime (&string[length], max - length, "%m/%d/%y", tm); | |
| 601 break; | |
| 602 case 'y': | |
| 603 length += | |
| 604 add_num2 (&string[length], tm->tm_year % 100, | |
| 605 max - length, pad); | |
| 606 break; | |
| 607 case 'Y': | |
| 608 add_char ((tm->tm_year + 1900) / 1000 + '0'); | |
| 609 length += | |
| 610 add_num3 (&string[length], | |
| 611 (1900 + tm->tm_year) % 1000, max - length, zero); | |
| 612 break; | |
|
5254
1537701f08a1
Support Roman month numbers, #'format-time-string
Aidan Kehoe <kehoea@parhasard.net>
parents:
5016
diff
changeset
|
613 case '\xe6': |
|
1537701f08a1
Support Roman month numbers, #'format-time-string
Aidan Kehoe <kehoea@parhasard.net>
parents:
5016
diff
changeset
|
614 length += |
|
1537701f08a1
Support Roman month numbers, #'format-time-string
Aidan Kehoe <kehoea@parhasard.net>
parents:
5016
diff
changeset
|
615 add_str (&string[length], roman_lower[tm->tm_mon], |
|
1537701f08a1
Support Roman month numbers, #'format-time-string
Aidan Kehoe <kehoea@parhasard.net>
parents:
5016
diff
changeset
|
616 max - length); |
|
1537701f08a1
Support Roman month numbers, #'format-time-string
Aidan Kehoe <kehoea@parhasard.net>
parents:
5016
diff
changeset
|
617 break; |
|
1537701f08a1
Support Roman month numbers, #'format-time-string
Aidan Kehoe <kehoea@parhasard.net>
parents:
5016
diff
changeset
|
618 case '\xC6': |
|
1537701f08a1
Support Roman month numbers, #'format-time-string
Aidan Kehoe <kehoea@parhasard.net>
parents:
5016
diff
changeset
|
619 length += |
|
1537701f08a1
Support Roman month numbers, #'format-time-string
Aidan Kehoe <kehoea@parhasard.net>
parents:
5016
diff
changeset
|
620 add_str (&string[length], roman_upper[tm->tm_mon], |
|
1537701f08a1
Support Roman month numbers, #'format-time-string
Aidan Kehoe <kehoea@parhasard.net>
parents:
5016
diff
changeset
|
621 max - length); |
|
1537701f08a1
Support Roman month numbers, #'format-time-string
Aidan Kehoe <kehoea@parhasard.net>
parents:
5016
diff
changeset
|
622 break; |
| 428 | 623 } |
| 624 } | |
| 625 } | |
| 626 add_char (0); | |
| 627 return length - 1; | |
| 628 } |
