strftime.c (17141) | strftime.c (17209) |
---|---|
1/* 2 * Copyright (c) 1989 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that the above copyright notice and this paragraph are 7 * duplicated in all such forms and that any documentation, 8 * advertising materials, and other materials related to such 9 * distribution and use acknowledge that the software was developed 10 * by the University of California, Berkeley. The name of the 11 * University may not be used to endorse or promote products derived 12 * from this software without specific prior written permission. 13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16 */ 17 18#ifdef LIBC_RCS 19static const char rcsid[] = | 1/* 2 * Copyright (c) 1989 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that the above copyright notice and this paragraph are 7 * duplicated in all such forms and that any documentation, 8 * advertising materials, and other materials related to such 9 * distribution and use acknowledge that the software was developed 10 * by the University of California, Berkeley. The name of the 11 * University may not be used to endorse or promote products derived 12 * from this software without specific prior written permission. 13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16 */ 17 18#ifdef LIBC_RCS 19static const char rcsid[] = |
20 "$Id: strftime.c,v 1.8 1996/05/27 06:54:01 scrappy Exp $"; | 20 "$Id: strftime.c,v 1.9 1996/07/12 18:55:32 jkh Exp $"; |
21#endif 22 23#ifndef lint 24#ifndef NOID | 21#endif 22 23#ifndef lint 24#ifndef NOID |
25static const char elsieid[] = "@(#)strftime.c 7.38"; | |
26/* | 25/* |
26static char elsieid[] = "@(#)strftime.c 7.47"; 27*/ 28/* |
|
27** Based on the UCB version with the ID appearing below. 28** This is ANSIish only when "multibyte character == plain character". 29*/ 30#endif /* !defined NOID */ 31#endif /* !defined lint */ 32 33#include "private.h" 34 --- 4 unchanged lines hidden (view full) --- 39#endif /* !defined LIBC_SCCS */ 40 41#include "tzfile.h" 42#include <fcntl.h> 43#include <locale.h> 44#include <rune.h> /* for _PATH_LOCALE */ 45#include <sys/stat.h> 46 | 29** Based on the UCB version with the ID appearing below. 30** This is ANSIish only when "multibyte character == plain character". 31*/ 32#endif /* !defined NOID */ 33#endif /* !defined lint */ 34 35#include "private.h" 36 --- 4 unchanged lines hidden (view full) --- 41#endif /* !defined LIBC_SCCS */ 42 43#include "tzfile.h" 44#include <fcntl.h> 45#include <locale.h> 46#include <rune.h> /* for _PATH_LOCALE */ 47#include <sys/stat.h> 48 |
47#define LOCALE_HOME _PATH_LOCALE 48 | |
49struct lc_time_T { 50 const char * mon[12]; 51 const char * month[12]; 52 const char * wday[7]; 53 const char * weekday[7]; 54 const char * X_fmt; 55 const char * x_fmt; 56 const char * c_fmt; --- 30 unchanged lines hidden (view full) --- 87 ** Since the C language standard calls for 88 ** "date, using locale's date format," anything goes. 89 ** Using just numbers (as here) makes Quakers happier; 90 ** it's also compatible with SVR4. 91 */ 92 "%m/%d/%y", 93 94 /* | 49struct lc_time_T { 50 const char * mon[12]; 51 const char * month[12]; 52 const char * wday[7]; 53 const char * weekday[7]; 54 const char * X_fmt; 55 const char * x_fmt; 56 const char * c_fmt; --- 30 unchanged lines hidden (view full) --- 87 ** Since the C language standard calls for 88 ** "date, using locale's date format," anything goes. 89 ** Using just numbers (as here) makes Quakers happier; 90 ** it's also compatible with SVR4. 91 */ 92 "%m/%d/%y", 93 94 /* |
95 ** c_fmt (ctime-compatible) | 95 ** c_fmt |
96 ** Note that 97 ** "%a %b %d %H:%M:%S %Y" 98 ** is used by Solaris 2.3. 99 */ | 96 ** Note that 97 ** "%a %b %d %H:%M:%S %Y" 98 ** is used by Solaris 2.3. 99 */ |
100 "%a %b %e %X %Y", | 100 "%D %X", /* %m/%d/%y %H:%M:%S */ |
101 102 /* am */ 103 "AM", 104 105 /* pm */ 106 "PM", 107 108 /* date_fmt */ | 101 102 /* am */ 103 "AM", 104 105 /* pm */ 106 "PM", 107 108 /* date_fmt */ |
109 "%a %b %e %X %Z %Y" | 109 "%a %b %e %H:%M:%S %Z %Y" |
110}; 111 112static char * _add P((const char *, char *, const char *)); 113static char * _conv P((int, const char *, char *, const char *)); 114static char * _fmt P((const char *, const struct tm *, char *, const char *)); | 110}; 111 112static char * _add P((const char *, char *, const char *)); 113static char * _conv P((int, const char *, char *, const char *)); 114static char * _fmt P((const char *, const struct tm *, char *, const char *)); |
115static char * _secs P((const struct tm *, char *, const char *)); | |
116 117size_t strftime P((char *, size_t, const char *, const struct tm *)); 118 119extern char * tzname[]; 120 121size_t 122strftime(s, maxsize, format, t) | 115 116size_t strftime P((char *, size_t, const char *, const struct tm *)); 117 118extern char * tzname[]; 119 120size_t 121strftime(s, maxsize, format, t) |
123 char *const s; 124 const size_t maxsize; 125 const char *const format; 126 const struct tm *const t; | 122char * const s; 123const size_t maxsize; 124const char * const format; 125const struct tm * const t; |
127{ | 126{ |
128 char *p; | 127 char * p; |
129 130 tzset(); 131 p = _fmt(((format == NULL) ? "%c" : format), t, s, s + maxsize); 132 if (p == s + maxsize) 133 return 0; 134 *p = '\0'; 135 return p - s; 136} 137 138static char * 139_fmt(format, t, pt, ptlim) | 128 129 tzset(); 130 p = _fmt(((format == NULL) ? "%c" : format), t, s, s + maxsize); 131 if (p == s + maxsize) 132 return 0; 133 *p = '\0'; 134 return p - s; 135} 136 137static char * 138_fmt(format, t, pt, ptlim) |
140 const char *format; 141 const struct tm *const t; 142 char *pt; 143 const char *const ptlim; | 139const char * format; 140const struct tm * const t; 141char * pt; 142const char * const ptlim; |
144{ 145 for ( ; *format; ++format) { 146 if (*format == '%') { 147label: 148 switch (*++format) { 149 case '\0': 150 --format; 151 break; --- 121 unchanged lines hidden (view full) --- 273 continue; 274 case 'r': 275 pt = _fmt("%I:%M:%S %p", t, pt, ptlim); 276 continue; 277 case 'S': 278 pt = _conv(t->tm_sec, "%02d", pt, ptlim); 279 continue; 280 case 's': | 143{ 144 for ( ; *format; ++format) { 145 if (*format == '%') { 146label: 147 switch (*++format) { 148 case '\0': 149 --format; 150 break; --- 121 unchanged lines hidden (view full) --- 272 continue; 273 case 'r': 274 pt = _fmt("%I:%M:%S %p", t, pt, ptlim); 275 continue; 276 case 'S': 277 pt = _conv(t->tm_sec, "%02d", pt, ptlim); 278 continue; 279 case 's': |
281 pt = _secs(t, pt, ptlim); | 280 { 281 struct tm tm; 282 char buf[INT_STRLEN_MAXIMUM( 283 time_t) + 1]; 284 time_t mkt; 285 286 tm = *t; 287 mkt = mktime(&tm); 288 if (TYPE_SIGNED(time_t)) 289 (void) sprintf(buf, "%ld", 290 (long) mkt); 291 else (void) sprintf(buf, "%lu", 292 (unsigned long) mkt); 293 pt = _add(buf, pt, ptlim); 294 } |
282 continue; 283 case 'T': 284 pt = _fmt("%H:%M:%S", t, pt, ptlim); 285 continue; 286 case 't': 287 pt = _add("\t", pt, ptlim); 288 continue; 289 case 'U': --- 5 unchanged lines hidden (view full) --- 295 ** From Arnold Robbins' strftime version 3.0: 296 ** "ISO 8601: Weekday as a decimal number 297 ** [1 (Monday) - 7]" 298 ** (ado, 5/24/93) 299 */ 300 pt = _conv((t->tm_wday == 0) ? 7 : t->tm_wday, 301 "%d", pt, ptlim); 302 continue; | 295 continue; 296 case 'T': 297 pt = _fmt("%H:%M:%S", t, pt, ptlim); 298 continue; 299 case 't': 300 pt = _add("\t", pt, ptlim); 301 continue; 302 case 'U': --- 5 unchanged lines hidden (view full) --- 308 ** From Arnold Robbins' strftime version 3.0: 309 ** "ISO 8601: Weekday as a decimal number 310 ** [1 (Monday) - 7]" 311 ** (ado, 5/24/93) 312 */ 313 pt = _conv((t->tm_wday == 0) ? 7 : t->tm_wday, 314 "%d", pt, ptlim); 315 continue; |
303 case 'V': 304 /* 305 ** From Arnold Robbins' strftime version 3.0: 306 ** "the week number of the year (the first 307 ** Monday as the first day of week 1) as a 308 ** decimal number (01-53). The method for 309 ** determining the week number is as specified 310 ** by ISO 8601 (to wit: if the week containing 311 ** January 1 has four or more days in the new 312 ** year, then it is week 1, otherwise it is 313 ** week 53 of the previous year and the next 314 ** week is week 1)." 315 ** (ado, 5/24/93) 316 */ 317 /* 318 ** XXX--If January 1 falls on a Friday, 319 ** January 1-3 are part of week 53 of the 320 ** previous year. By analogy, if January 321 ** 1 falls on a Thursday, are December 29-31 322 ** of the PREVIOUS year part of week 1??? 323 ** (ado 5/24/93) 324 */ 325 /* 326 ** You are understood not to expect this. 327 */ | 316 case 'V': /* ISO 8601 week number */ 317 case 'G': /* ISO 8601 year (four digits) */ 318 case 'g': /* ISO 8601 year (two digits) */ 319/* 320** From Arnold Robbins' strftime version 3.0: "the week number of the 321** year (the first Monday as the first day of week 1) as a decimal number 322** (01-53)." 323** (ado, 1993-05-24) 324** 325** From "http://www.ft.uni-erlangen.de/~mskuhn/iso-time.html" by Markus Kuhn: 326** "Week 01 of a year is per definition the first week which has the 327** Thursday in this year, which is equivalent to the week which contains 328** the fourth day of January. In other words, the first week of a new year 329** is the week which has the majority of its days in the new year. Week 01 330** might also contain days from the previous year and the week before week 331** 01 of a year is the last week (52 or 53) of the previous year even if 332** it contains days from the new year. A week starts with Monday (day 1) 333** and ends with Sunday (day 7). For example, the first week of the year 334** 1997 lasts from 1996-12-30 to 1997-01-05..." 335** (ado, 1996-01-02) 336*/ |
328 { | 337 { |
329 int i; | 338 int year; 339 int yday; 340 int wday; 341 int w; |
330 | 342 |
331 i = (t->tm_yday + 10 - (t->tm_wday ? 332 (t->tm_wday - 1) : 6)) / 7; 333 if (i == 0) { | 343 year = t->tm_year + TM_YEAR_BASE; 344 yday = t->tm_yday; 345 wday = t->tm_wday; 346 for ( ; ; ) { 347 int len; 348 int bot; 349 int top; 350 351 len = isleap(year) ? 352 DAYSPERLYEAR : 353 DAYSPERNYEAR; |
334 /* | 354 /* |
335 ** What day of the week does 336 ** January 1 fall on? | 355 ** What yday (-3 ... 3) does 356 ** the ISO year begin on? |
337 */ | 357 */ |
338 i = t->tm_wday - 339 (t->tm_yday - 1); | 358 bot = ((yday + 11 - wday) % 359 DAYSPERWEEK) - 3; |
340 /* | 360 /* |
341 ** Fri Jan 1: 53 342 ** Sun Jan 1: 52 343 ** Sat Jan 1: 53 if previous 344 ** year a leap 345 ** year, else 52 | 361 ** What yday does the NEXT 362 ** ISO year begin on? |
346 */ | 363 */ |
347 if (i == TM_FRIDAY) 348 i = 53; 349 else if (i == TM_SUNDAY) 350 i = 52; 351 else i = isleap(t->tm_year + 352 TM_YEAR_BASE) ? 353 53 : 52; | 364 top = bot - 365 (len % DAYSPERWEEK); 366 if (top < -3) 367 top += DAYSPERWEEK; 368 top += len; 369 if (yday >= top) { 370 ++year; 371 w = 1; 372 break; 373 } 374 if (yday >= bot) { 375 w = 1 + ((yday - bot) / 376 DAYSPERWEEK); 377 break; 378 } 379 --year; 380 yday += isleap(year) ? 381 DAYSPERLYEAR : 382 DAYSPERNYEAR; 383 } |
354#ifdef XPG4_1994_04_09 | 384#ifdef XPG4_1994_04_09 |
355 /* 356 ** As of 4/9/94, though, 357 ** XPG4 calls for 53 358 ** unconditionally. 359 */ 360 i = 53; | 385 if (w == 52 && t->tm_mon == TM_JANUARY) 386 w = 53; |
361#endif /* defined XPG4_1994_04_09 */ | 387#endif /* defined XPG4_1994_04_09 */ |
362 } 363 pt = _conv(i, "%02d", pt, ptlim); | 388 if (*format == 'V') 389 pt = _conv(w, "%02d", 390 pt, ptlim); 391 else if (*format == 'G') 392 pt = _conv(year, "%02d", 393 pt, ptlim); 394 else pt = _conv(year, "%04d", 395 pt, ptlim); |
364 } 365 continue; 366 case 'v': 367 /* 368 ** From Arnold Robbins' strftime version 3.0: 369 ** "date as dd-bbb-YYYY" 370 ** (ado, 5/24/93) 371 */ --- 48 unchanged lines hidden (view full) --- 420 break; 421 *pt++ = *format; 422 } 423 return pt; 424} 425 426static char * 427_conv(n, format, pt, ptlim) | 396 } 397 continue; 398 case 'v': 399 /* 400 ** From Arnold Robbins' strftime version 3.0: 401 ** "date as dd-bbb-YYYY" 402 ** (ado, 5/24/93) 403 */ --- 48 unchanged lines hidden (view full) --- 452 break; 453 *pt++ = *format; 454 } 455 return pt; 456} 457 458static char * 459_conv(n, format, pt, ptlim) |
428 const int n; 429 const char *const format; 430 char *const pt; 431 const char *const ptlim; | 460const int n; 461const char * const format; 462char * const pt; 463const char * const ptlim; |
432{ 433 char buf[INT_STRLEN_MAXIMUM(int) + 1]; 434 435 (void) sprintf(buf, format, n); 436 return _add(buf, pt, ptlim); 437} 438 439static char * --- 10 unchanged lines hidden (view full) --- 450 tmp = *t; 451 s = mktime(&tmp); 452 (void) sprintf(buf, "%ld", s); 453 return _add(buf, pt, ptlim); 454} 455 456static char * 457_add(str, pt, ptlim) | 464{ 465 char buf[INT_STRLEN_MAXIMUM(int) + 1]; 466 467 (void) sprintf(buf, format, n); 468 return _add(buf, pt, ptlim); 469} 470 471static char * --- 10 unchanged lines hidden (view full) --- 482 tmp = *t; 483 s = mktime(&tmp); 484 (void) sprintf(buf, "%ld", s); 485 return _add(buf, pt, ptlim); 486} 487 488static char * 489_add(str, pt, ptlim) |
458 const char *str; 459 char *pt; 460 const char *const ptlim; | 490const char * str; 491char * pt; 492const char * const ptlim; |
461{ 462 while (pt < ptlim && (*pt = *str++) != '\0') 463 ++pt; 464 return pt; 465} 466 467extern char *_PathLocale; 468 --- 107 unchanged lines hidden --- | 493{ 494 while (pt < ptlim && (*pt = *str++) != '\0') 495 ++pt; 496 return pt; 497} 498 499extern char *_PathLocale; 500 --- 107 unchanged lines hidden --- |