3 ** Originally written by Steven M. Bellovin <smb@research.att.com> while
4 ** at the University of North Carolina at Chapel Hill. Later tweaked by
5 ** a couple of people on Usenet. Completely overhauled by Rich $alz
6 ** <rsalz@bbn.com> and Jim Berets <jberets@bbn.com> in August, 1990.
8 ** This code is in the public domain and has no copyright.
18 /* Since the code of getdate.y is not included in the Emacs executable
19 itself, there is no need to #define static in this file. Even if
20 the code were included in the Emacs executable, it probably
21 wouldn't do any harm to #undef it here; this will only cause
22 problems if we try to write to a static variable, which I don't
23 think this code needs to do. */
31 #if defined (STDC_HEADERS) || (!defined (isascii) && !defined (HAVE_ISASCII))
32 # define IN_CTYPE_DOMAIN(c) 1
34 # define IN_CTYPE_DOMAIN(c) isascii(c)
37 #define ISSPACE(c) (IN_CTYPE_DOMAIN (c) && isspace (c))
38 #define ISALPHA(c) (IN_CTYPE_DOMAIN (c) && isalpha (c))
39 #define ISUPPER(c) (IN_CTYPE_DOMAIN (c) && isupper (c))
40 #define ISDIGIT_LOCALE(c) (IN_CTYPE_DOMAIN (c) && isdigit (c))
42 /* ISDIGIT differs from ISDIGIT_LOCALE, as follows:
43 - Its arg may be any int or unsigned int; it need not be an unsigned char.
44 - It's guaranteed to evaluate its argument exactly once.
45 - It's typically faster.
46 Posix 1003.2-1992 section 2.5.2.1 page 50 lines 1556-1558 says that
47 only '0' through '9' are digits. Prefer ISDIGIT to ISDIGIT_LOCALE unless
48 it's important to use the locale's definition of `digit' even when the
49 host does not conform to Posix. */
50 #define ISDIGIT(c) ((unsigned) (c) - '0' <= 9)
52 #if defined (STDC_HEADERS) || defined (USG)
56 #if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)
57 # define __attribute__(x)
60 #ifndef ATTRIBUTE_UNUSED
61 # define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
64 /* Some old versions of bison generate parsers that use bcopy.
65 That loses on systems that don't provide the function, so we have
66 to redefine it here. */
67 #if !defined (HAVE_BCOPY) && defined (HAVE_MEMCPY) && !defined (bcopy)
68 # define bcopy(from, to, len) memcpy ((to), (from), (len))
71 /* Remap normal yacc parser interface names (yyparse, yylex, yyerror, etc),
72 as well as gratuitiously global symbol names, so we can have multiple
73 yacc generated parsers in the same program. Note that these are only
74 the variables produced by yacc. If other parser generators (bison,
75 byacc, etc) produce additional global names that conflict at link time,
76 then those parser generators need to be fixed instead of adding those
77 names to this list. */
79 #define yymaxdepth gd_maxdepth
80 #define yyparse gd_parse
82 #define yyerror gd_error
83 #define yylval gd_lval
84 #define yychar gd_char
85 #define yydebug gd_debug
86 #define yypact gd_pact
93 #define yyexca gd_exca
94 #define yyerrflag gd_errflag
95 #define yynerrs gd_nerrs
100 #define yystate gd_state
103 #define yy_yyv gd_yyv
105 #define yylloc gd_lloc
106 #define yyreds gd_reds /* With YYDEBUG defined */
107 #define yytoks gd_toks /* With YYDEBUG defined */
108 #define yylhs gd_yylhs
109 #define yylen gd_yylen
110 #define yydefred gd_yydefred
111 #define yydgoto gd_yydgoto
112 #define yysindex gd_yysindex
113 #define yyrindex gd_yyrindex
114 #define yygindex gd_yygindex
115 #define yytable gd_yytable
116 #define yycheck gd_yycheck
119 static int yyerror ();
122 #define HOUR(x) ((x) * 60)
124 #define MAX_BUFF_LEN 128 /* size of buffer to read the date into */
127 ** An entry in the lexical lookup table.
129 typedef struct _TABLE {
137 ** Meridian: am, pm, or 24-hour style.
139 typedef enum _MERIDIAN {
145 ** Global variables. We could get rid of most of these by using a good
146 ** union as the yacc stack. (This routine was originally written before
147 ** yacc had the %union construct.) Maybe someday; right now we only use
148 ** the %union very rarely.
150 static const char *yyInput;
151 static int yyDayOrdinal;
152 static int yyDayNumber;
153 static int yyHaveDate;
154 static int yyHaveDay;
155 static int yyHaveRel;
156 static int yyHaveTime;
157 static int yyHaveZone;
158 static int yyTimezone;
161 static int yyMinutes;
163 static int yySeconds;
165 static MERIDIAN yyMeridian;
167 static int yyRelHour;
168 static int yyRelMinutes;
169 static int yyRelMonth;
170 static int yyRelSeconds;
171 static int yyRelYear;
175 /* This grammar has 13 shift/reduce conflicts. */
180 enum _MERIDIAN Meridian;
183 %token tAGO tDAY tDAY_UNIT tDAYZONE tDST tHOUR_UNIT tID
184 %token tMERIDIAN tMINUTE_UNIT tMONTH tMONTH_UNIT
185 %token tSEC_UNIT tSNUMBER tUNUMBER tYEAR_UNIT tZONE
187 %type <Number> tDAY tDAY_UNIT tDAYZONE tHOUR_UNIT tMINUTE_UNIT
188 %type <Number> tMONTH tMONTH_UNIT
189 %type <Number> tSEC_UNIT tSNUMBER tUNUMBER tYEAR_UNIT tZONE
190 %type <Meridian> tMERIDIAN o_merid
216 time : tUNUMBER tMERIDIAN {
222 | tUNUMBER ':' tUNUMBER o_merid {
228 | tUNUMBER ':' tUNUMBER tSNUMBER {
234 ? -$4 % 100 + (-$4 / 100) * 60
235 : - ($4 % 100 + ($4 / 100) * 60));
237 | tUNUMBER ':' tUNUMBER ':' tUNUMBER o_merid {
243 | tUNUMBER ':' tUNUMBER ':' tUNUMBER tSNUMBER {
250 ? -$6 % 100 + (-$6 / 100) * 60
251 : - ($6 % 100 + ($6 / 100) * 60));
259 yyTimezone = $1 - 60;
263 yyTimezone = $1 - 60;
281 date : tUNUMBER '/' tUNUMBER {
285 | tUNUMBER '/' tUNUMBER '/' tUNUMBER {
286 /* Interpret as YYYY/MM/DD if $1 >= 1000, otherwise as MM/DD/YY.
287 The goal in recognizing YYYY/MM/DD is solely to support legacy
288 machine-generated dates like those in an RCS log listing. If
289 you want portability, use the ISO 8601 format. */
303 | tUNUMBER tSNUMBER tSNUMBER {
304 /* ISO 8601 format. yyyy-mm-dd. */
309 | tUNUMBER tMONTH tSNUMBER {
310 /* e.g. 17-JUN-1992. */
319 | tMONTH tUNUMBER ',' tUNUMBER {
328 | tUNUMBER tMONTH tUNUMBER {
336 yyRelSeconds = -yyRelSeconds;
337 yyRelMinutes = -yyRelMinutes;
338 yyRelHour = -yyRelHour;
339 yyRelDay = -yyRelDay;
340 yyRelMonth = -yyRelMonth;
341 yyRelYear = -yyRelYear;
346 relunit : tUNUMBER tYEAR_UNIT {
347 yyRelYear += $1 * $2;
349 | tSNUMBER tYEAR_UNIT {
350 yyRelYear += $1 * $2;
355 | tUNUMBER tMONTH_UNIT {
356 yyRelMonth += $1 * $2;
358 | tSNUMBER tMONTH_UNIT {
359 yyRelMonth += $1 * $2;
364 | tUNUMBER tDAY_UNIT {
367 | tSNUMBER tDAY_UNIT {
373 | tUNUMBER tHOUR_UNIT {
374 yyRelHour += $1 * $2;
376 | tSNUMBER tHOUR_UNIT {
377 yyRelHour += $1 * $2;
382 | tUNUMBER tMINUTE_UNIT {
383 yyRelMinutes += $1 * $2;
385 | tSNUMBER tMINUTE_UNIT {
386 yyRelMinutes += $1 * $2;
391 | tUNUMBER tSEC_UNIT {
392 yyRelSeconds += $1 * $2;
394 | tSNUMBER tSEC_UNIT {
395 yyRelSeconds += $1 * $2;
404 if (yyHaveTime && yyHaveDate && !yyHaveRel)
412 yyMonth= ($1/100)%100;
426 yyMinutes = $1 % 100;
447 /* Include this file down here because bison inserts code above which
448 may define-away `const'. We want the prototype for get_date to have
449 the same signature as the function definition does. */
452 extern struct tm *gmtime ();
453 extern struct tm *localtime ();
454 extern time_t mktime ();
456 /* Month and day table. */
457 static TABLE const MonthDayTable[] = {
458 { "january", tMONTH, 1 },
459 { "february", tMONTH, 2 },
460 { "march", tMONTH, 3 },
461 { "april", tMONTH, 4 },
462 { "may", tMONTH, 5 },
463 { "june", tMONTH, 6 },
464 { "july", tMONTH, 7 },
465 { "august", tMONTH, 8 },
466 { "september", tMONTH, 9 },
467 { "sept", tMONTH, 9 },
468 { "october", tMONTH, 10 },
469 { "november", tMONTH, 11 },
470 { "december", tMONTH, 12 },
471 { "sunday", tDAY, 0 },
472 { "monday", tDAY, 1 },
473 { "tuesday", tDAY, 2 },
475 { "wednesday", tDAY, 3 },
476 { "wednes", tDAY, 3 },
477 { "thursday", tDAY, 4 },
479 { "thurs", tDAY, 4 },
480 { "friday", tDAY, 5 },
481 { "saturday", tDAY, 6 },
485 /* Time units table. */
486 static TABLE const UnitsTable[] = {
487 { "year", tYEAR_UNIT, 1 },
488 { "month", tMONTH_UNIT, 1 },
489 { "fortnight", tDAY_UNIT, 14 },
490 { "week", tDAY_UNIT, 7 },
491 { "day", tDAY_UNIT, 1 },
492 { "hour", tHOUR_UNIT, 1 },
493 { "minute", tMINUTE_UNIT, 1 },
494 { "min", tMINUTE_UNIT, 1 },
495 { "second", tSEC_UNIT, 1 },
496 { "sec", tSEC_UNIT, 1 },
500 /* Assorted relative-time words. */
501 static TABLE const OtherTable[] = {
502 { "tomorrow", tMINUTE_UNIT, 1 * 24 * 60 },
503 { "yesterday", tMINUTE_UNIT, -1 * 24 * 60 },
504 { "today", tMINUTE_UNIT, 0 },
505 { "now", tMINUTE_UNIT, 0 },
506 { "last", tUNUMBER, -1 },
507 { "this", tMINUTE_UNIT, 0 },
508 { "next", tUNUMBER, 1 },
509 { "first", tUNUMBER, 1 },
510 /* { "second", tUNUMBER, 2 }, */
511 { "third", tUNUMBER, 3 },
512 { "fourth", tUNUMBER, 4 },
513 { "fifth", tUNUMBER, 5 },
514 { "sixth", tUNUMBER, 6 },
515 { "seventh", tUNUMBER, 7 },
516 { "eighth", tUNUMBER, 8 },
517 { "ninth", tUNUMBER, 9 },
518 { "tenth", tUNUMBER, 10 },
519 { "eleventh", tUNUMBER, 11 },
520 { "twelfth", tUNUMBER, 12 },
525 /* The timezone table. */
526 static TABLE const TimezoneTable[] = {
527 { "gmt", tZONE, HOUR ( 0) }, /* Greenwich Mean */
528 { "ut", tZONE, HOUR ( 0) }, /* Universal (Coordinated) */
529 { "utc", tZONE, HOUR ( 0) },
530 { "wet", tZONE, HOUR ( 0) }, /* Western European */
531 { "bst", tDAYZONE, HOUR ( 0) }, /* British Summer */
532 { "wat", tZONE, HOUR ( 1) }, /* West Africa */
533 { "at", tZONE, HOUR ( 2) }, /* Azores */
535 /* For completeness. BST is also British Summer, and GST is
536 * also Guam Standard. */
537 { "bst", tZONE, HOUR ( 3) }, /* Brazil Standard */
538 { "gst", tZONE, HOUR ( 3) }, /* Greenland Standard */
541 { "nft", tZONE, HOUR (3.5) }, /* Newfoundland */
542 { "nst", tZONE, HOUR (3.5) }, /* Newfoundland Standard */
543 { "ndt", tDAYZONE, HOUR (3.5) }, /* Newfoundland Daylight */
545 { "ast", tZONE, HOUR ( 4) }, /* Atlantic Standard */
546 { "adt", tDAYZONE, HOUR ( 4) }, /* Atlantic Daylight */
547 { "est", tZONE, HOUR ( 5) }, /* Eastern Standard */
548 { "edt", tDAYZONE, HOUR ( 5) }, /* Eastern Daylight */
549 { "cst", tZONE, HOUR ( 6) }, /* Central Standard */
550 { "cdt", tDAYZONE, HOUR ( 6) }, /* Central Daylight */
551 { "mst", tZONE, HOUR ( 7) }, /* Mountain Standard */
552 { "mdt", tDAYZONE, HOUR ( 7) }, /* Mountain Daylight */
553 { "pst", tZONE, HOUR ( 8) }, /* Pacific Standard */
554 { "pdt", tDAYZONE, HOUR ( 8) }, /* Pacific Daylight */
555 { "yst", tZONE, HOUR ( 9) }, /* Yukon Standard */
556 { "ydt", tDAYZONE, HOUR ( 9) }, /* Yukon Daylight */
557 { "hst", tZONE, HOUR (10) }, /* Hawaii Standard */
558 { "hdt", tDAYZONE, HOUR (10) }, /* Hawaii Daylight */
559 { "cat", tZONE, HOUR (10) }, /* Central Alaska */
560 { "ahst", tZONE, HOUR (10) }, /* Alaska-Hawaii Standard */
561 { "nt", tZONE, HOUR (11) }, /* Nome */
562 { "idlw", tZONE, HOUR (12) }, /* International Date Line West */
563 { "cet", tZONE, -HOUR (1) }, /* Central European */
564 { "met", tZONE, -HOUR (1) }, /* Middle European */
565 { "mewt", tZONE, -HOUR (1) }, /* Middle European Winter */
566 { "mest", tDAYZONE, -HOUR (1) }, /* Middle European Summer */
567 { "mesz", tDAYZONE, -HOUR (1) }, /* Middle European Summer */
568 { "swt", tZONE, -HOUR (1) }, /* Swedish Winter */
569 { "sst", tDAYZONE, -HOUR (1) }, /* Swedish Summer */
570 { "fwt", tZONE, -HOUR (1) }, /* French Winter */
571 { "fst", tDAYZONE, -HOUR (1) }, /* French Summer */
572 { "eet", tZONE, -HOUR (2) }, /* Eastern Europe, USSR Zone 1 */
573 { "bt", tZONE, -HOUR (3) }, /* Baghdad, USSR Zone 2 */
575 { "it", tZONE, -HOUR (3.5) },/* Iran */
577 { "zp4", tZONE, -HOUR (4) }, /* USSR Zone 3 */
578 { "zp5", tZONE, -HOUR (5) }, /* USSR Zone 4 */
580 { "ist", tZONE, -HOUR (5.5) },/* Indian Standard */
582 { "zp6", tZONE, -HOUR (6) }, /* USSR Zone 5 */
584 /* For completeness. NST is also Newfoundland Standard, and SST is
585 * also Swedish Summer. */
586 { "nst", tZONE, -HOUR (6.5) },/* North Sumatra */
587 { "sst", tZONE, -HOUR (7) }, /* South Sumatra, USSR Zone 6 */
589 { "wast", tZONE, -HOUR (7) }, /* West Australian Standard */
590 { "wadt", tDAYZONE, -HOUR (7) }, /* West Australian Daylight */
592 { "jt", tZONE, -HOUR (7.5) },/* Java (3pm in Cronusland!) */
594 { "cct", tZONE, -HOUR (8) }, /* China Coast, USSR Zone 7 */
595 { "jst", tZONE, -HOUR (9) }, /* Japan Standard, USSR Zone 8 */
597 { "cast", tZONE, -HOUR (9.5) },/* Central Australian Standard */
598 { "cadt", tDAYZONE, -HOUR (9.5) },/* Central Australian Daylight */
600 { "east", tZONE, -HOUR (10) }, /* Eastern Australian Standard */
601 { "eadt", tDAYZONE, -HOUR (10) }, /* Eastern Australian Daylight */
602 { "gst", tZONE, -HOUR (10) }, /* Guam Standard, USSR Zone 9 */
603 { "nzt", tZONE, -HOUR (12) }, /* New Zealand */
604 { "nzst", tZONE, -HOUR (12) }, /* New Zealand Standard */
605 { "nzdt", tDAYZONE, -HOUR (12) }, /* New Zealand Daylight */
606 { "idle", tZONE, -HOUR (12) }, /* International Date Line East */
610 /* Military timezone table. */
611 static TABLE const MilitaryTable[] = {
612 { "a", tZONE, HOUR ( 1) },
613 { "b", tZONE, HOUR ( 2) },
614 { "c", tZONE, HOUR ( 3) },
615 { "d", tZONE, HOUR ( 4) },
616 { "e", tZONE, HOUR ( 5) },
617 { "f", tZONE, HOUR ( 6) },
618 { "g", tZONE, HOUR ( 7) },
619 { "h", tZONE, HOUR ( 8) },
620 { "i", tZONE, HOUR ( 9) },
621 { "k", tZONE, HOUR ( 10) },
622 { "l", tZONE, HOUR ( 11) },
623 { "m", tZONE, HOUR ( 12) },
624 { "n", tZONE, HOUR (- 1) },
625 { "o", tZONE, HOUR (- 2) },
626 { "p", tZONE, HOUR (- 3) },
627 { "q", tZONE, HOUR (- 4) },
628 { "r", tZONE, HOUR (- 5) },
629 { "s", tZONE, HOUR (- 6) },
630 { "t", tZONE, HOUR (- 7) },
631 { "u", tZONE, HOUR (- 8) },
632 { "v", tZONE, HOUR (- 9) },
633 { "w", tZONE, HOUR (-10) },
634 { "x", tZONE, HOUR (-11) },
635 { "y", tZONE, HOUR (-12) },
636 { "z", tZONE, HOUR ( 0) },
646 char *s ATTRIBUTE_UNUSED;
652 ToHour (Hours, Meridian)
659 if (Hours < 0 || Hours > 23)
663 if (Hours < 1 || Hours > 12)
669 if (Hours < 1 || Hours > 12)
687 /* XPG4 suggests that years 00-68 map to 2000-2068, and
688 years 69-99 map to 1969-1999. */
703 register const TABLE *tp;
707 /* Make it lowercase. */
708 for (p = buff; *p; p++)
712 if (strcmp (buff, "am") == 0 || strcmp (buff, "a.m.") == 0)
714 yylval.Meridian = MERam;
717 if (strcmp (buff, "pm") == 0 || strcmp (buff, "p.m.") == 0)
719 yylval.Meridian = MERpm;
723 /* See if we have an abbreviation for a month. */
724 if (strlen (buff) == 3)
726 else if (strlen (buff) == 4 && buff[3] == '.')
734 for (tp = MonthDayTable; tp->name; tp++)
738 if (strncmp (buff, tp->name, 3) == 0)
740 yylval.Number = tp->value;
744 else if (strcmp (buff, tp->name) == 0)
746 yylval.Number = tp->value;
751 for (tp = TimezoneTable; tp->name; tp++)
752 if (strcmp (buff, tp->name) == 0)
754 yylval.Number = tp->value;
758 if (strcmp (buff, "dst") == 0)
761 for (tp = UnitsTable; tp->name; tp++)
762 if (strcmp (buff, tp->name) == 0)
764 yylval.Number = tp->value;
768 /* Strip off any plural and try the units table again. */
769 i = strlen (buff) - 1;
773 for (tp = UnitsTable; tp->name; tp++)
774 if (strcmp (buff, tp->name) == 0)
776 yylval.Number = tp->value;
779 buff[i] = 's'; /* Put back for "this" in OtherTable. */
782 for (tp = OtherTable; tp->name; tp++)
783 if (strcmp (buff, tp->name) == 0)
785 yylval.Number = tp->value;
789 /* Military timezones. */
790 if (buff[1] == '\0' && ISALPHA (*buff))
792 for (tp = MilitaryTable; tp->name; tp++)
793 if (strcmp (buff, tp->name) == 0)
795 yylval.Number = tp->value;
800 /* Drop out any periods and try the timezone table again. */
801 for (i = 0, p = q = buff; *q; q++)
808 for (tp = TimezoneTable; tp->name; tp++)
809 if (strcmp (buff, tp->name) == 0)
811 yylval.Number = tp->value;
829 while (ISSPACE (*yyInput))
832 if (ISDIGIT (c = *yyInput) || c == '-' || c == '+')
834 if (c == '-' || c == '+')
836 sign = c == '-' ? -1 : 1;
837 if (!ISDIGIT (*++yyInput))
838 /* skip the '-' sign */
843 for (yylval.Number = 0; ISDIGIT (c = *yyInput++);)
844 yylval.Number = 10 * yylval.Number + c - '0';
847 yylval.Number = -yylval.Number;
848 return sign ? tSNUMBER : tUNUMBER;
852 for (p = buff; (c = *yyInput++, ISALPHA (c)) || c == '.';)
853 if (p < &buff[sizeof buff - 1])
857 return LookupWord (buff);
876 #define TM_YEAR_ORIGIN 1900
878 /* Yield A - B, measured in seconds. */
880 difftm (struct tm *a, struct tm *b)
882 int ay = a->tm_year + (TM_YEAR_ORIGIN - 1);
883 int by = b->tm_year + (TM_YEAR_ORIGIN - 1);
885 /* difference in day of year */
886 a->tm_yday - b->tm_yday
887 /* + intervening leap days */
888 + ((ay >> 2) - (by >> 2))
889 - (ay / 100 - by / 100)
890 + ((ay / 100 >> 2) - (by / 100 >> 2))
891 /* + difference in years * 365 */
892 + (long) (ay - by) * 365
894 return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour))
895 + (a->tm_min - b->tm_min))
896 + (a->tm_sec - b->tm_sec));
900 get_date (const char *p, const time_t *now)
902 struct tm tm, tm0, *tmp;
906 Start = now ? *now : time ((time_t *) NULL);
907 tmp = localtime (&Start);
910 yyYear = tmp->tm_year + TM_YEAR_ORIGIN;
911 yyMonth = tmp->tm_mon + 1;
912 yyDay = tmp->tm_mday;
913 yyHour = tmp->tm_hour;
914 yyMinutes = tmp->tm_min;
915 yySeconds = tmp->tm_sec;
916 tm.tm_isdst = tmp->tm_isdst;
931 || yyHaveTime > 1 || yyHaveZone > 1 || yyHaveDate > 1 || yyHaveDay > 1)
934 tm.tm_year = ToYear (yyYear) - TM_YEAR_ORIGIN + yyRelYear;
935 tm.tm_mon = yyMonth - 1 + yyRelMonth;
936 tm.tm_mday = yyDay + yyRelDay;
937 if (yyHaveTime || (yyHaveRel && !yyHaveDate && !yyHaveDay))
939 tm.tm_hour = ToHour (yyHour, yyMeridian);
942 tm.tm_min = yyMinutes;
943 tm.tm_sec = yySeconds;
947 tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
949 tm.tm_hour += yyRelHour;
950 tm.tm_min += yyRelMinutes;
951 tm.tm_sec += yyRelSeconds;
954 Start = mktime (&tm);
956 if (Start == (time_t) -1)
959 /* Guard against falsely reporting errors near the time_t boundaries
960 when parsing times in other time zones. For example, if the min
961 time_t value is 1970-01-01 00:00:00 UTC and we are 8 hours ahead
962 of UTC, then the min localtime value is 1970-01-01 08:00:00; if
963 we apply mktime to 1970-01-01 00:00:00 we will get an error, so
964 we apply mktime to 1970-01-02 08:00:00 instead and adjust the time
965 zone by 24 hours to compensate. This algorithm assumes that
966 there is no DST transition within a day of the time_t boundaries. */
970 if (tm.tm_year <= EPOCH - TM_YEAR_ORIGIN)
973 yyTimezone -= 24 * 60;
978 yyTimezone += 24 * 60;
980 Start = mktime (&tm);
983 if (Start == (time_t) -1)
987 if (yyHaveDay && !yyHaveDate)
989 tm.tm_mday += ((yyDayNumber - tm.tm_wday + 7) % 7
990 + 7 * (yyDayOrdinal - (0 < yyDayOrdinal)));
991 Start = mktime (&tm);
992 if (Start == (time_t) -1)
999 struct tm *gmt = gmtime (&Start);
1002 delta = yyTimezone * 60L + difftm (&tm, gmt);
1003 if ((Start + delta < Start) != (delta < 0))
1004 return -1; /* time_t overflow */
1019 char buff[MAX_BUFF_LEN + 1];
1022 (void) printf ("Enter date, or blank line to exit.\n\t> ");
1023 (void) fflush (stdout);
1025 buff[MAX_BUFF_LEN] = 0;
1026 while (fgets (buff, MAX_BUFF_LEN, stdin) && buff[0])
1028 d = get_date (buff, (time_t *) NULL);
1030 (void) printf ("Bad format - couldn't convert.\n");
1032 (void) printf ("%s", ctime (&d));
1033 (void) printf ("\t> ");
1034 (void) fflush (stdout);
1039 #endif /* defined (TEST) */