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