58 #include <sys/types.h> 61 #if defined(TM_IN_SYS_TIME) || !defined(GAWK) 62 #include <sys/types.h> 74 #define MAILHEADER_EXT 1 75 #define ISO_DATE_EXT 1 77 #if defined(ISO_DATE_EXT) 78 #if ! defined(POSIX2_DATE) 83 #if defined(POSIX2_DATE) 84 #if ! defined(SYSV_EXT) 87 #if ! defined(SUNOS_EXT) 92 #if defined(POSIX2_DATE) 93 #define adddecl(stuff) stuff 95 #define adddecl(stuff) 101 #if !defined __STDC__ && !defined _WIN32 108 static int weeknumber(
const struct tm *timeptr,
int firstweekday);
125 #define range(low, item, hi) max((low), min((item), (hi))) 140 return (a < b ? a : b);
156 return (a > b ? a : b);
159 #ifdef NO_STRING_LITERAL_CONCATENATION 160 #error No string literal concatenation 163 #define add(x,y) (rb_funcall((x), '+', 1, (y))) 164 #define sub(x,y) (rb_funcall((x), '-', 1, (y))) 165 #define mul(x,y) (rb_funcall((x), '*', 1, (y))) 166 #define quo(x,y) (rb_funcall((x), rb_intern("quo"), 1, (y))) 167 #define div(x,y) (rb_funcall((x), rb_intern("div"), 1, (y))) 168 #define mod(x,y) (rb_funcall((x), '%', 1, (y))) 176 char *endp = s + maxsize;
183 int precision, flags, colons;
185 enum {LEFT, CHCASE, LOWER, UPPER, LOCALE_O, LOCALE_E};
186 #define BIT_OF(n) (1U<<(n)) 189 static const char days_l[][10] = {
190 "Sunday",
"Monday",
"Tuesday",
"Wednesday",
191 "Thursday",
"Friday",
"Saturday",
193 static const char months_l[][10] = {
194 "January",
"February",
"March",
"April",
195 "May",
"June",
"July",
"August",
"September",
196 "October",
"November",
"December",
198 static const char ampm[][3] = {
"AM",
"PM", };
210 for (; *format && s < endp - 1; format++) {
211 #define FLAG_FOUND() do { \ 212 if (precision > 0 || flags & (BIT_OF(LOCALE_E)|BIT_OF(LOCALE_O))) \ 215 #define NEEDS(n) do if (s >= endp || (n) >= endp - s - 1) goto err; while (0) 216 #define FILL_PADDING(i) do { \ 217 if (!(flags & BIT_OF(LEFT)) && precision > (i)) { \ 219 memset(s, padding ? padding : ' ', precision - (i)); \ 220 s += precision - (i); \ 226 #define FMT(def_pad, def_prec, fmt, val) \ 229 if (precision <= 0) precision = (def_prec); \ 230 if (flags & BIT_OF(LEFT)) precision = 1; \ 231 l = snprintf(s, endp - s, \ 232 ((padding == '0' || (!padding && (def_pad) == '0')) ? "%0*"fmt : "%*"fmt), \ 234 if (l < 0) goto err; \ 237 #define STRFTIME(fmt) \ 239 i = date_strftime_with_tmx(s, endp - s, (fmt), tmx); \ 241 if (precision > i) {\ 242 if (start + maxsize < s + precision) { \ 246 memmove(s + precision - i, s, i);\ 247 memset(s, padding ? padding : ' ', precision - i); \ 252 #define FMTV(def_pad, def_prec, fmt, val) \ 255 if (FIXNUM_P(tmp)) { \ 256 FMT((def_pad), (def_prec), "l"fmt, FIX2LONG(tmp)); \ 259 VALUE args[2], result; \ 261 if (precision <= 0) precision = (def_prec); \ 262 if (flags & BIT_OF(LEFT)) precision = 1; \ 263 args[0] = INT2FIX(precision); \ 265 if (padding == '0' || (!padding && (def_pad) == '0')) \ 266 result = rb_str_format(2, args, rb_str_new2("%0*"fmt)); \ 268 result = rb_str_format(2, args, rb_str_new2("%*"fmt)); \ 269 l = strlcpy(s, StringValueCStr(result), endp-s); \ 270 if ((size_t)(endp-s) <= l) \ 276 if (*format !=
'%') {
298 if (flags &
BIT_OF(CHCASE)) {
304 if (wday < 0 || wday > 6)
307 i = 3, tp = days_l[wday];
312 if (flags &
BIT_OF(CHCASE)) {
318 if (wday < 0 || wday > 6)
329 if (flags &
BIT_OF(CHCASE)) {
335 if (mon < 1 || mon > 12)
338 i = 3, tp = months_l[mon-1];
343 if (flags &
BIT_OF(CHCASE)) {
349 if (mon < 1 || mon > 12)
352 i =
strlen(tp = months_l[mon-1]);
362 FMT(
'0', 2,
"d", (
int)
i);
367 FMT(
'0', 2,
"d", (
int)
i);
376 FMT(
'0', 2,
"d", (
int)
i);
385 FMT(
'0', 2,
"d", (
int)
i);
390 FMT(
'0', 2,
"d", (
int)
i);
395 if ((*format ==
'p' && (flags &
BIT_OF(CHCASE))) ||
396 (*format ==
'P' && !(flags & (
BIT_OF(CHCASE)|
BIT_OF(UPPER))))) {
418 FMT(
'0', 2,
"d", (
int)
i);
427 FMT(
'0', 1,
"d", (
int)
i);
444 FMT(
'0', 2,
"d", (
int)
i);
452 FMT(
'0', 0 <= y ? 4 : 5,
"ld", y);
455 FMTV(
'0', 4,
"d", year);
460 #ifdef MAILHEADER_EXT 472 if ((aoff / 3600) < 10)
477 if (flags &
BIT_OF(LEFT) && hl == 1)
482 precision = precision <= (3 + hw) ? hw : precision-3;
483 NEEDS(precision + 3);
487 precision = precision <= (4 + hw) ? hw : precision-4;
488 NEEDS(precision + 4);
492 precision = precision <= (7 + hw) ? hw : precision-7;
493 NEEDS(precision + 7);
498 if (aoff % 3600 == 0) {
499 precision = precision <= (1 + hw) ? hw : precision-1;
500 NEEDS(precision + 3);
502 else if (aoff % 60 == 0) {
503 precision = precision <= (4 + hw) ? hw : precision-4;
504 NEEDS(precision + 4);
507 precision = precision <= (7 + hw) ? hw : precision-7;
508 NEEDS(precision + 7);
517 if (padding ==
' ' && precision > hl) {
518 i =
snprintf(s, endp - s,
"%*s", precision - hl,
"");
529 i =
snprintf(s, endp - s,
"%.*ld", precision, off / 3600);
533 if (colons == 3 && off == 0)
537 i =
snprintf(s, endp - s,
"%02d", (
int)(off / 60));
541 if (colons == 3 && off == 0)
545 i =
snprintf(s, endp - s,
"%02d", (
int)off);
554 if (flags &
BIT_OF(CHCASE)) {
603 FMT(
' ', 2,
"d", (
int)
i);
612 FMT(
' ', 2,
"d", (
int)
i);
629 flags |=
BIT_OF(LOCALE_E);
630 if (*(format + 1) &&
strchr(
"cCxXyY", *(format + 1)))
635 flags |=
BIT_OF(LOCALE_O);
636 if (*(format + 1) &&
strchr(
"deHImMSuUVwWy",
653 FMT(
'0', 2,
"d", (
int)
i);
661 FMT(
'0', 0 <= y ? 4 : 5,
"ld", y);
664 FMTV(
'0', 4,
"d", year);
686 if (precision <= 0) {
727 STRFTIME(
"%a %b %e %H:%M:%S %Z %Y");
733 padding = precision = 0;
757 case '1':
case '2':
case '3':
case '4':
758 case '5':
case '6':
case '7':
case '8':
case '9':
761 precision = (int)strtoul(format, &e, 10);
799 if (*format ==
'\0') {
825 return ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0);
844 #if defined(HAVE_STRUCT_TM_TM_GMTOFF) 847 #if defined(HAVE_TM_ZONE) 859 const struct tm *timeptr;
879 int weeknum, jan1day;
897 jan1day = timeptr->tm_wday - (timeptr->tm_yday % 7);
926 #ifdef USE_BROKEN_XPG4 935 dec31ly.tm_mday = 31;
936 dec31ly.tm_wday = (jan1day == 0) ? 6 : jan1day - 1;
937 dec31ly.tm_yday = 364 +
isleap(dec31ly.tm_year + 1900L);
944 if (timeptr->tm_mon == 11) {
958 wday = timeptr->tm_wday;
959 mday = timeptr->tm_mday;
960 if ( (wday == 1 && (mday >= 29 && mday <= 31))
961 || (wday == 2 && (mday == 30 || mday == 31))
962 || (wday == 3 && mday == 31))
973 tmx2tm_noyear(
tmx, &tm);
986 const struct tm *timeptr;
990 weeknumber(
const struct tm *timeptr,
int firstweekday)
993 int wday = timeptr->tm_wday;
996 if (firstweekday == 1) {
1002 ret = ((timeptr->tm_yday + 7 - wday) / 7);
1012 tmx2tm_noyear(
tmx, &tm);
1020 Date: Wed, 24 Apr 91 20:54:08 MDT
1021 From: Michal Jaegermann <audfax!emory!vm.ucs.UAlberta.CA!NTOMCZAK>
1022 To: arnold@audiofax.com
1025 in a process of fixing of strftime() in libraries on Atari ST
I grabbed
1026 some pieces of code from your own strftime. When doing that it came
1027 to mind that your
weeknumber() function compiles a little bit nicer
1028 in the following form:
1033 return (timeptr->tm_yday - timeptr->tm_wday +
1034 (firstweekday ? (timeptr->tm_wday ? 8 : 1) : 7)) / 7;
1036 How nicer it depends on a compiler, of course, but always a tiny bit.
1040 ntomczak@vm.ucs.ualberta.ca
1043 #ifdef TEST_STRFTIME 1076 #include <sys/time.h> 1085 static char *array[] =
1087 "(%%A) full weekday name, var length (Sunday..Saturday) %A",
1088 "(%%B) full month name, var length (January..December) %B",
1090 "(%%D) date (%%m/%%d/%%y) %D",
1091 "(%%E) Locale extensions (ignored) %E",
1092 "(%%H) hour (24-hour clock, 00..23) %H",
1093 "(%%I) hour (12-hour clock, 01..12) %I",
1094 "(%%M) minute (00..59) %M",
1095 "(%%O) Locale extensions (ignored) %O",
1096 "(%%R) time, 24-hour (%%H:%%M) %R",
1097 "(%%S) second (00..60) %S",
1098 "(%%T) time, 24-hour (%%H:%%M:%%S) %T",
1099 "(%%U) week of year, Sunday as first day of week (00..53) %U",
1100 "(%%V) week of year according to ISO 8601 %V",
1101 "(%%W) week of year, Monday as first day of week (00..53) %W",
1102 "(%%X) appropriate locale time representation (%H:%M:%S) %X",
1103 "(%%Y) year with century (1970...) %Y",
1104 "(%%Z) timezone (EDT), or blank if timezone not determinable %Z",
1105 "(%%a) locale's abbreviated weekday name (Sun..Sat) %a",
1106 "(%%b) locale's abbreviated month name (Jan..Dec) %b",
1107 "(%%c) full date (Sat Nov 4 12:02:33 1989)%n%t%t%t %c",
1108 "(%%d) day of the month (01..31) %d",
1109 "(%%e) day of the month, blank-padded ( 1..31) %e",
1110 "(%%h) should be same as (%%b) %h",
1111 "(%%j) day of the year (001..366) %j",
1112 "(%%k) hour, 24-hour clock, blank pad ( 0..23) %k",
1113 "(%%l) hour, 12-hour clock, blank pad ( 1..12) %l",
1114 "(%%m) month (01..12) %m",
1115 "(%%p) locale's AM or PM based on 12-hour clock %p",
1116 "(%%r) time, 12-hour (same as %%I:%%M:%%S %%p) %r",
1117 "(%%u) ISO 8601: Weekday as decimal number [1 (Monday) - 7] %u",
1118 "(%%v) VMS date (dd-bbb-YYYY) %v",
1119 "(%%w) day of week (0..6, Sunday == 0) %w",
1120 "(%%x) appropriate locale date representation %x",
1121 "(%%y) last two digits of year (00..99) %y",
1122 "(%%z) timezone offset east of GMT as HHMM (e.g. -0500) %z",
1134 char string[MAXTIME];
1146 tm = localtime(&clock);
1148 for (k = 0; next = array[k]; k++) {
1149 length = strftime(
string, MAXTIME, next, tm);
1150 printf(
"%s\n",
string);
static long NUM2LONG(VALUE x)
size_t strlen(const char *)
#define FMT(def_pad, def_prec, fmt, val)
static int max(int a, int b)
static int isleap(long year)
static int iso8601wknum_v(const struct vtm *vtm)
VALUE rb_funcall(VALUE, ID, int,...)
Calls a method.
static size_t date_strftime_with_tmx(char *s, size_t maxsize, const char *format, const struct tmx *tmx)
static int iso8601wknum(struct tm *timeptr) const
static int min(int a, int b)
size_t date_strftime(char *s, size_t maxsize, const char *format, const struct tmx *tmx)
#define range(low, item, hi)
VALUE rb_str_format(int, const VALUE *, VALUE)
#define FMTV(def_pad, def_prec, fmt, val)
RUBY_EXTERN size_t strlcpy(char *, const char *, size_t)
#define StringValueCStr(v)
static int weeknumber_v(const struct vtm *vtm, int firstweekday)
int main(int argc, char **argv)
VALUE rb_str_new2(const char *)