~vcs-imports/gawk/master

« back to all changes in this revision

Viewing changes to missing/strftime.c

  • Committer: Arnold D. Robbins
  • Date: 2010-07-16 09:41:09 UTC
  • Revision ID: git-v1:8c042f99cc7465c86351d21331a129111b75345d
Tags: gawk-3.0.0
Move to gawk-3.0.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
10
10
 * For extensions from SunOS, add SUNOS_EXT.
11
11
 * For stuff needed to implement the P1003.2 date command, add POSIX2_DATE.
12
12
 * For VMS dates, add VMS_EXT.
 
13
 * For a an RFC822 time format, add MAILHEADER_EXT.
 
14
 * For ISO week years, add ISO_DATE_EXT.
13
15
 * For complete POSIX semantics, add POSIX_SEMANTICS.
14
16
 *
15
 
 * The code for %c, %x, and %X is my best guess as to what's "appropriate".
 
17
 * The code for %c, %x, and %X now follows the 1003.2 specification for
 
18
 * the POSIX locale.
16
19
 * This version ignores LOCALE information.
17
20
 * It also doesn't worry about multi-byte characters.
18
21
 * So there.
26
29
 * Updated April, 1993
27
30
 * Updated February, 1994
28
31
 * Updated May, 1994
 
32
 * Updated January, 1995
 
33
 * Updated September, 1995
 
34
 * Updated January, 1996
29
35
 *
30
36
 * Fixes from ado@elsie.nci.nih.gov
31
37
 * February 1991, May 1992
33
39
 * May, 1993
34
40
 * Further fixes from ado@elsie.nci.nih.gov
35
41
 * February 1994
 
42
 * %z code from chip@chinacat.unicom.com
 
43
 * Applied September 1995
 
44
 * %V code fixed (again) and %G, %g added,
 
45
 * January 1996
36
46
 */
37
47
 
38
 
/************ for gawk 2.15.5 ***************/
39
 
#ifndef TZNAME_MISSING
40
 
#define HAVE_TZNAME
41
 
#endif
42
 
#ifndef TM_ZONE_MISSING
43
 
#define HAVE_TM_ZONE
44
 
#endif
45
 
/*********** end of for gawk 2.15.5 *********/
46
 
 
47
48
#ifndef GAWK
48
49
#include <stdio.h>
49
50
#include <ctype.h>
60
61
#define SUNOS_EXT       1       /* stuff in SunOS strftime routine */
61
62
#define POSIX2_DATE     1       /* stuff in Posix 1003.2 date command */
62
63
#define VMS_EXT         1       /* include %v for VMS date format */
 
64
#define MAILHEADER_EXT  1       /* add %z for HHMM format */
 
65
#define ISO_DATE_EXT    1       /* %G and %g for year of ISO week */
63
66
#ifndef GAWK
64
67
#define POSIX_SEMANTICS 1       /* call tzset() if TZ changes */
65
68
#endif
66
69
 
 
70
#if defined(ISO_DATE_EXT)
 
71
#if ! defined(POSIX2_DATE)
 
72
#define POSIX2_DATE     1
 
73
#endif
 
74
#endif
 
75
 
67
76
#if defined(POSIX2_DATE)
68
77
#if ! defined(SYSV_EXT)
69
78
#define SYSV_EXT        1
111
120
#if !defined(OS2) && !defined(MSDOS) && defined(HAVE_TZNAME)
112
121
extern char *tzname[2];
113
122
extern int daylight;
114
 
#endif
 
123
#ifdef SOLARIS
 
124
extern long timezone, altzone;
 
125
#else
 
126
extern int timezone, altzone;
 
127
#endif
 
128
#endif
 
129
 
 
130
#undef min      /* just in case */
115
131
 
116
132
/* min --- return minimum of two numbers */
117
133
 
127
143
        return (a < b ? a : b);
128
144
}
129
145
 
 
146
#undef max      /* also, just in case */
 
147
 
130
148
/* max --- return maximum of two numbers */
131
149
 
132
150
#ifndef __STDC__
158
176
        char *endp = s + maxsize;
159
177
        char *start = s;
160
178
        auto char tbuf[100];
161
 
        int i;
 
179
        long off;
 
180
        int i, w, y;
162
181
        static short first = 1;
163
182
#ifdef POSIX_SEMANTICS
164
183
        static char *savetz = NULL;
166
185
        char *tz;
167
186
#endif /* POSIX_SEMANTICS */
168
187
#ifndef HAVE_TM_ZONE
 
188
#ifndef HAVE_TM_NAME
 
189
#ifndef HAVE_TZNAME
169
190
        extern char *timezone();
170
191
        struct timeval tv;
171
192
        struct timezone zone;
 
193
#endif /* HAVE_TZNAME */
 
194
#endif /* HAVE_TM_NAME */
172
195
#endif /* HAVE_TM_ZONE */
173
196
 
174
197
        /* various tables, useful in North America */
281
304
                        break;
282
305
 
283
306
                case 'c':       /* appropriate date and time representation */
284
 
                        sprintf(tbuf, "%s %s %2d %02d:%02d:%02d %d",
285
 
                                days_a[range(0, timeptr->tm_wday, 6)],
286
 
                                months_a[range(0, timeptr->tm_mon, 11)],
287
 
                                range(1, timeptr->tm_mday, 31),
288
 
                                range(0, timeptr->tm_hour, 23),
289
 
                                range(0, timeptr->tm_min, 59),
290
 
                                range(0, timeptr->tm_sec, 61),
291
 
                                timeptr->tm_year + 1900);
 
307
                        strftime(tbuf, sizeof tbuf, "%a %b %e %H:%M:%S %Y", timeptr);
292
308
                        break;
293
309
 
294
310
                case 'd':       /* day of the month, 01 - 31 */
351
367
                        break;
352
368
 
353
369
                case 'x':       /* appropriate date representation */
354
 
                        sprintf(tbuf, "%s %s %2d %d",
355
 
                                days_a[range(0, timeptr->tm_wday, 6)],
356
 
                                months_a[range(0, timeptr->tm_mon, 11)],
357
 
                                range(1, timeptr->tm_mday, 31),
358
 
                                timeptr->tm_year + 1900);
 
370
                        strftime(tbuf, sizeof tbuf, "%m/%d/%y", timeptr);
359
371
                        break;
360
372
 
361
373
                case 'X':       /* appropriate time representation */
362
 
                        sprintf(tbuf, "%02d:%02d:%02d",
363
 
                                range(0, timeptr->tm_hour, 23),
364
 
                                range(0, timeptr->tm_min, 59),
365
 
                                range(0, timeptr->tm_sec, 61));
 
374
                        strftime(tbuf, sizeof tbuf, "%H:%M:%S", timeptr);
366
375
                        break;
367
376
 
368
377
                case 'y':       /* year without a century, 00 - 99 */
374
383
                        sprintf(tbuf, "%d", 1900 + timeptr->tm_year);
375
384
                        break;
376
385
 
 
386
#ifdef MAILHEADER_EXT
 
387
                /*
 
388
                 * From: Chip Rosenthal <chip@chinacat.unicom.com>
 
389
                 * Date: Sun, 19 Mar 1995 00:33:29 -0600 (CST)
 
390
                 * 
 
391
                 * Warning: the %z [code] is implemented by inspecting the
 
392
                 * timezone name conditional compile settings, and
 
393
                 * inferring a method to get timezone offsets. I've tried
 
394
                 * this code on a couple of machines, but I don't doubt
 
395
                 * there is some system out there that won't like it.
 
396
                 * Maybe the easiest thing to do would be to bracket this
 
397
                 * with an #ifdef that can turn it off. The %z feature
 
398
                 * would be an admittedly obscure one that most folks can
 
399
                 * live without, but it would be a great help to those of
 
400
                 * us that muck around with various message processors.
 
401
                 */
 
402
                case 'z':       /* time zone offset east of GMT e.g. -0600 */
 
403
#ifdef HAVE_TM_NAME
 
404
                        /*
 
405
                         * Systems with tm_name probably have tm_tzadj as
 
406
                         * secs west of GMT.  Convert to mins east of GMT.
 
407
                         */
 
408
                        off = -timeptr->tm_tzadj / 60;
 
409
#else /* !HAVE_TM_NAME */
 
410
#ifdef HAVE_TM_ZONE
 
411
                        /*
 
412
                         * Systems with tm_zone probably have tm_gmtoff as
 
413
                         * secs east of GMT.  Convert to mins east of GMT.
 
414
                         */
 
415
                        off = timeptr->tm_gmtoff / 60;
 
416
#else /* !HAVE_TM_ZONE */
 
417
#if HAVE_TZNAME
 
418
                        /*
 
419
                         * Systems with tzname[] probably have timezone as
 
420
                         * secs west of GMT.  Convert to mins east of GMT.
 
421
                         */
 
422
                        off = -(daylight ? timezone : altzone) / 60;
 
423
#else /* !HAVE_TZNAME */
 
424
                        off = -zone.tz_minuteswest;
 
425
#endif /* !HAVE_TZNAME */
 
426
#endif /* !HAVE_TM_ZONE */
 
427
#endif /* !HAVE_TM_NAME */
 
428
                        if (off < 0) {
 
429
                                tbuf[0] = '-';
 
430
                                off = -off;
 
431
                        } else {
 
432
                                tbuf[0] = '+';
 
433
                        }
 
434
                        sprintf(tbuf+1, "%02d%02d", off/60, off%60);
 
435
                        break;
 
436
#endif /* MAILHEADER_EXT */
 
437
 
377
438
                case 'Z':       /* time zone name or abbrevation */
378
439
#ifdef HAVE_TZNAME
379
 
                        i = (daylight && timeptr->tm_isdst);    /* 0 or 1 */
 
440
                        i = (daylight && timeptr->tm_isdst > 0); /* 0 or 1 */
380
441
                        strcpy(tbuf, tzname[i]);
381
442
#else
382
443
#ifdef HAVE_TM_ZONE
383
444
                        strcpy(tbuf, timeptr->tm_zone);
384
445
#else
 
446
#ifdef HAVE_TM_NAME
 
447
                        strcpy(tbuf, timeptr->tm_name);
 
448
#else
385
449
                        gettimeofday(& tv, & zone);
386
450
                        strcpy(tbuf, timezone(zone.tz_minuteswest,
387
 
                                                timeptr->tm_isdst));
388
 
#endif
389
 
#endif
 
451
                                                timeptr->tm_isdst > 0));
 
452
#endif /* HAVE_TM_NAME */
 
453
#endif /* HAVE_TM_ZONE */
 
454
#endif /* HAVE_TZNAME */
390
455
                        break;
391
456
 
392
457
#ifdef SYSV_EXT
462
527
                        goto again;
463
528
 
464
529
                case 'V':       /* week of year according ISO 8601 */
465
 
#if defined(GAWK) && defined(VMS_EXT)
466
 
                {
467
 
                        extern int do_lint;
468
 
                        extern void warning();
469
 
                        static int warned = 0;
470
 
 
471
 
                        if (! warned && do_lint) {
472
 
                                warned = 1;
473
 
                                warning(
474
 
        "conversion %%V added in P1003.2; for VMS style date, use %%v");
475
 
                        }
476
 
                }
477
 
#endif
478
530
                        sprintf(tbuf, "%02d", iso8601wknum(timeptr));
479
531
                        break;
480
532
 
484
536
                                        timeptr->tm_wday);
485
537
                        break;
486
538
#endif  /* POSIX2_DATE */
 
539
 
 
540
#ifdef ISO_DATE_EXT
 
541
                case 'G':
 
542
                case 'g':
 
543
                        /*
 
544
                         * Year of ISO week.
 
545
                         *
 
546
                         * If it's December but the ISO week number is one,
 
547
                         * that week is in next year.
 
548
                         * If it's January but the ISO week number is 52 or
 
549
                         * 53, that week is in last year.
 
550
                         * Otherwise, it's this year.
 
551
                         */
 
552
                        w = iso8601wknum(timeptr);
 
553
                        if (timeptr->tm_mon == 11 && w == 1)
 
554
                                y = 1900 + timeptr->tm_year + 1;
 
555
                        else if (timeptr->tm_mon == 0 && w >= 52)
 
556
                                y = 1900 + timeptr->tm_year - 1;
 
557
                        else
 
558
                                y = 1900 + timeptr->tm_year;
 
559
 
 
560
                        if (*format == 'G')
 
561
                                sprintf(tbuf, "%d", y);
 
562
                        else
 
563
                                sprintf(tbuf, "%02d", y % 100);
 
564
                        break;
 
565
#endif ISO_DATE_EXT
487
566
                default:
488
567
                        tbuf[0] = '%';
489
568
                        tbuf[1] = *format;
539
618
         *      If the week (Monday to Sunday) containing January 1
540
619
         *      has four or more days in the new year, then it is week 1;
541
620
         *      otherwise it is the highest numbered week of the previous
542
 
         *      (52 or 53) year, and the next week is week 1.
 
621
         *      year (52 or 53), and the next week is week 1.
543
622
         *
544
623
         * ADR: This means if Jan 1 was Monday through Thursday,
545
624
         *      it was week 1, otherwise week 52 or 53.
587
666
        case 1:         /* Monday */
588
667
                break;
589
668
        case 2:         /* Tuesday */
590
 
        case 3:         /* Wednedsday */
 
669
        case 3:         /* Wednesday */
591
670
        case 4:         /* Thursday */
592
671
                weeknum++;
593
672
                break;
612
691
                }
613
692
                break;
614
693
        }
 
694
 
 
695
        if (timeptr->tm_mon == 11) {
 
696
                /*
 
697
                 * The last week of the year
 
698
                 * can be in week 1 of next year.
 
699
                 * Sigh.
 
700
                 *
 
701
                 * This can only happen if
 
702
                 *      M   T  W
 
703
                 *      29  30 31
 
704
                 *      30  31
 
705
                 *      31
 
706
                 */
 
707
                int wday, mday;
 
708
 
 
709
                wday = timeptr->tm_wday;
 
710
                mday = timeptr->tm_mday;
 
711
                if (   (wday == 1 && (mday >= 29 && mday <= 31))
 
712
                    || (wday == 2 && (mday == 30 || mday == 31))
 
713
                    || (wday == 3 &&  mday == 31))
 
714
                        weeknum = 1;
 
715
        }
 
716
 
615
717
        return weeknum;
616
718
}
617
719
#endif
749
851
        "(%%w)                       day of week (0..6, Sunday == 0)  %w",
750
852
        "(%%x)                appropriate locale date representation  %x",
751
853
        "(%%y)                      last two digits of year (00..99)  %y",
 
854
        "(%%z)      timezone offset east of GMT as HHMM (e.g. -0500)  %z",
752
855
        (char *) NULL
753
856
};
754
857