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 grammar has 10 shift/reduce conflicts.
10 ** This code is in the public domain and has no copyright.
12 /* SUPPRESS 287 on yaccpar_sccsid *//* Unused static variable */
13 /* SUPPRESS 288 on yyerrlab *//* Label unused */
15 /* $FreeBSD: src/usr.bin/find/getdate.y,v 1.2.4.1 2003/01/22 03:26:34 peter Exp $ */
16 /* $DragonFly: src/usr.bin/find/getdate.y,v 1.2 2003/06/17 04:29:26 dillon Exp $ */
21 /* The code at the top of get_date which figures out the offset of the
22 current time zone checks various CPP symbols to see if special
23 tricks are need, but defaults to using the gettimeofday system call.
24 Include <sys/time.h> if that will be used. */
28 #else /* defined(vms) */
29 # include <sys/types.h>
30 # include <sys/time.h>
31 # include <sys/timeb.h>
32 #endif /* !defined(vms) */
34 #if defined (__STDC__) || defined (USG)
38 /* Some old versions of bison generate parsers that use bcopy.
39 That loses on systems that don't provide the function, so we have
40 to redefine it here. */
41 #if !defined (HAVE_BCOPY) && defined (HAVE_MEMCPY) && !defined (bcopy)
42 #define bcopy(from, to, len) memcpy ((to), (from), (len))
45 #if defined (__STDC__)
49 /* NOTES on rebuilding getdate.c (particularly for inclusion in CVS
52 We don't want to mess with all the portability hassles of alloca.
53 In particular, most (all?) versions of bison will use alloca in
54 their parser. If bison works on your system (e.g. it should work
55 with gcc), then go ahead and use it, but the more general solution
56 is to use byacc instead of bison, which should generate a portable
57 parser. I played with adding "#define alloca dont_use_alloca", to
58 give an error if the parser generator uses alloca (and thus detect
59 unportable getdate.c's), but that seems to cause as many problems
62 extern
struct tm
*gmtime
();
63 extern
struct tm
*localtime
();
65 #define yyparse getdate_yyparse
66 #define yylex getdate_yylex
67 #define yyerror getdate_yyerror
69 static int yyparse ();
71 static int yyerror ();
74 #define HOUR(x) ((time_t)(x) * 60)
75 #define SECSPERDAY (24L * 60L * 60L)
79 ** An entry in the lexical lookup table.
81 typedef
struct _TABLE
{
89 ** Daylight-savings mode: on, off, or not yet known.
91 typedef
enum _DSTMODE
{
92 DSTon
, DSToff
, DSTmaybe
96 ** Meridian: am, pm, or 24-hour style.
98 typedef
enum _MERIDIAN
{
104 ** Global variables. We could get rid of most of these by using a good
105 ** union as the yacc stack. (This routine was originally written before
106 ** yacc had the %union construct.) Maybe someday; right now we only use
107 ** the %union very rarely.
109 static char *yyInput
;
110 static DSTMODE yyDSTmode
;
111 static time_t yyDayOrdinal
;
112 static time_t yyDayNumber
;
113 static int yyHaveDate
;
114 static int yyHaveDay
;
115 static int yyHaveRel
;
116 static int yyHaveTime
;
117 static int yyHaveZone
;
118 static time_t yyTimezone
;
120 static time_t yyHour
;
121 static time_t yyMinutes
;
122 static time_t yyMonth
;
123 static time_t yySeconds
;
124 static time_t yyYear
;
125 static MERIDIAN yyMeridian
;
126 static time_t yyRelMonth
;
127 static time_t yyRelSeconds
;
133 enum _MERIDIAN Meridian
;
136 %token tAGO tDAY tDAYZONE tID tMERIDIAN tMINUTE_UNIT tMONTH tMONTH_UNIT
137 %token tSEC_UNIT tSNUMBER tUNUMBER tZONE tDST
139 %type
<Number
> tDAY tDAYZONE tMINUTE_UNIT tMONTH tMONTH_UNIT
140 %type
<Number
> tSEC_UNIT tSNUMBER tUNUMBER tZONE
141 %type
<Meridian
> tMERIDIAN o_merid
167 time
: tUNUMBER tMERIDIAN
{
173 | tUNUMBER
':' tUNUMBER o_merid
{
179 | tUNUMBER
':' tUNUMBER tSNUMBER
{
184 yyTimezone
= - ($4 %
100 + ($4 / 100) * 60);
186 | tUNUMBER
':' tUNUMBER
':' tUNUMBER o_merid
{
192 | tUNUMBER
':' tUNUMBER
':' tUNUMBER tSNUMBER
{
198 yyTimezone
= - ($6 %
100 + ($6 / 100) * 60);
231 date
: tUNUMBER
'/' tUNUMBER
{
235 | tUNUMBER
'/' tUNUMBER
'/' tUNUMBER
{
246 | tUNUMBER tSNUMBER tSNUMBER
{
247 /* ISO 8601 format. yyyy-mm-dd. */
252 | tUNUMBER tMONTH tSNUMBER
{
253 /* e.g. 17-JUN-1992. */
262 | tMONTH tUNUMBER
',' tUNUMBER
{
271 | tUNUMBER tMONTH tUNUMBER
{
279 yyRelSeconds
= -yyRelSeconds
;
280 yyRelMonth
= -yyRelMonth
;
285 relunit
: tUNUMBER tMINUTE_UNIT
{
286 yyRelSeconds
+= $1 * $2 * 60L;
288 | tSNUMBER tMINUTE_UNIT
{
289 yyRelSeconds
+= $1 * $2 * 60L;
292 yyRelSeconds
+= $1 * 60L;
294 | tSNUMBER tSEC_UNIT
{
297 | tUNUMBER tSEC_UNIT
{
303 | tSNUMBER tMONTH_UNIT
{
304 yyRelMonth
+= $1 * $2;
306 | tUNUMBER tMONTH_UNIT
{
307 yyRelMonth
+= $1 * $2;
315 if
(yyHaveTime
&& yyHaveDate
&& !yyHaveRel
)
321 yyMonth
= ($1/100)%
100;
332 yyMinutes
= $1 %
100;
341 o_merid
: /* NULL */ {
351 /* Month and day table. */
352 static TABLE
const MonthDayTable
[] = {
353 { "january", tMONTH
, 1 },
354 { "february", tMONTH
, 2 },
355 { "march", tMONTH
, 3 },
356 { "april", tMONTH
, 4 },
357 { "may", tMONTH
, 5 },
358 { "june", tMONTH
, 6 },
359 { "july", tMONTH
, 7 },
360 { "august", tMONTH
, 8 },
361 { "september", tMONTH
, 9 },
362 { "sept", tMONTH
, 9 },
363 { "october", tMONTH
, 10 },
364 { "november", tMONTH
, 11 },
365 { "december", tMONTH
, 12 },
366 { "sunday", tDAY
, 0 },
367 { "monday", tDAY
, 1 },
368 { "tuesday", tDAY
, 2 },
370 { "wednesday", tDAY
, 3 },
371 { "wednes", tDAY
, 3 },
372 { "thursday", tDAY
, 4 },
374 { "thurs", tDAY
, 4 },
375 { "friday", tDAY
, 5 },
376 { "saturday", tDAY
, 6 },
380 /* Time units table. */
381 static TABLE
const UnitsTable
[] = {
382 { "year", tMONTH_UNIT
, 12 },
383 { "month", tMONTH_UNIT
, 1 },
384 { "fortnight", tMINUTE_UNIT
, 14 * 24 * 60 },
385 { "week", tMINUTE_UNIT
, 7 * 24 * 60 },
386 { "day", tMINUTE_UNIT
, 1 * 24 * 60 },
387 { "hour", tMINUTE_UNIT
, 60 },
388 { "minute", tMINUTE_UNIT
, 1 },
389 { "min", tMINUTE_UNIT
, 1 },
390 { "second", tSEC_UNIT
, 1 },
391 { "sec", tSEC_UNIT
, 1 },
395 /* Assorted relative-time words. */
396 static TABLE
const OtherTable
[] = {
397 { "tomorrow", tMINUTE_UNIT
, 1 * 24 * 60 },
398 { "yesterday", tMINUTE_UNIT
, -1 * 24 * 60 },
399 { "today", tMINUTE_UNIT
, 0 },
400 { "now", tMINUTE_UNIT
, 0 },
401 { "last", tUNUMBER
, -1 },
402 { "this", tMINUTE_UNIT
, 0 },
403 { "next", tUNUMBER
, 2 },
404 { "first", tUNUMBER
, 1 },
405 /* { "second", tUNUMBER, 2 }, */
406 { "third", tUNUMBER
, 3 },
407 { "fourth", tUNUMBER
, 4 },
408 { "fifth", tUNUMBER
, 5 },
409 { "sixth", tUNUMBER
, 6 },
410 { "seventh", tUNUMBER
, 7 },
411 { "eighth", tUNUMBER
, 8 },
412 { "ninth", tUNUMBER
, 9 },
413 { "tenth", tUNUMBER
, 10 },
414 { "eleventh", tUNUMBER
, 11 },
415 { "twelfth", tUNUMBER
, 12 },
420 /* The timezone table. */
421 /* Some of these are commented out because a time_t can't store a float. */
422 static TABLE
const TimezoneTable
[] = {
423 { "gmt", tZONE
, HOUR
( 0) }, /* Greenwich Mean */
424 { "ut", tZONE
, HOUR
( 0) }, /* Universal (Coordinated) */
425 { "utc", tZONE
, HOUR
( 0) },
426 { "wet", tZONE
, HOUR
( 0) }, /* Western European */
427 { "bst", tDAYZONE
, HOUR
( 0) }, /* British Summer */
428 { "wat", tZONE
, HOUR
( 1) }, /* West Africa */
429 { "at", tZONE
, HOUR
( 2) }, /* Azores */
431 /* For completeness. BST is also British Summer, and GST is
432 * also Guam Standard. */
433 { "bst", tZONE
, HOUR
( 3) }, /* Brazil Standard */
434 { "gst", tZONE
, HOUR
( 3) }, /* Greenland Standard */
437 { "nft", tZONE
, HOUR
(3.5) }, /* Newfoundland */
438 { "nst", tZONE
, HOUR
(3.5) }, /* Newfoundland Standard */
439 { "ndt", tDAYZONE
, HOUR
(3.5) }, /* Newfoundland Daylight */
441 { "ast", tZONE
, HOUR
( 4) }, /* Atlantic Standard */
442 { "adt", tDAYZONE
, HOUR
( 4) }, /* Atlantic Daylight */
443 { "est", tZONE
, HOUR
( 5) }, /* Eastern Standard */
444 { "edt", tDAYZONE
, HOUR
( 5) }, /* Eastern Daylight */
445 { "cst", tZONE
, HOUR
( 6) }, /* Central Standard */
446 { "cdt", tDAYZONE
, HOUR
( 6) }, /* Central Daylight */
447 { "mst", tZONE
, HOUR
( 7) }, /* Mountain Standard */
448 { "mdt", tDAYZONE
, HOUR
( 7) }, /* Mountain Daylight */
449 { "pst", tZONE
, HOUR
( 8) }, /* Pacific Standard */
450 { "pdt", tDAYZONE
, HOUR
( 8) }, /* Pacific Daylight */
451 { "yst", tZONE
, HOUR
( 9) }, /* Yukon Standard */
452 { "ydt", tDAYZONE
, HOUR
( 9) }, /* Yukon Daylight */
453 { "hst", tZONE
, HOUR
(10) }, /* Hawaii Standard */
454 { "hdt", tDAYZONE
, HOUR
(10) }, /* Hawaii Daylight */
455 { "cat", tZONE
, HOUR
(10) }, /* Central Alaska */
456 { "ahst", tZONE
, HOUR
(10) }, /* Alaska-Hawaii Standard */
457 { "nt", tZONE
, HOUR
(11) }, /* Nome */
458 { "idlw", tZONE
, HOUR
(12) }, /* International Date Line West */
459 { "cet", tZONE
, -HOUR
(1) }, /* Central European */
460 { "met", tZONE
, -HOUR
(1) }, /* Middle European */
461 { "mewt", tZONE
, -HOUR
(1) }, /* Middle European Winter */
462 { "mest", tDAYZONE
, -HOUR
(1) }, /* Middle European Summer */
463 { "swt", tZONE
, -HOUR
(1) }, /* Swedish Winter */
464 { "sst", tDAYZONE
, -HOUR
(1) }, /* Swedish Summer */
465 { "fwt", tZONE
, -HOUR
(1) }, /* French Winter */
466 { "fst", tDAYZONE
, -HOUR
(1) }, /* French Summer */
467 { "eet", tZONE
, -HOUR
(2) }, /* Eastern Europe, USSR Zone 1 */
468 { "bt", tZONE
, -HOUR
(3) }, /* Baghdad, USSR Zone 2 */
470 { "it", tZONE
, -HOUR
(3.5) },/* Iran */
472 { "zp4", tZONE
, -HOUR
(4) }, /* USSR Zone 3 */
473 { "zp5", tZONE
, -HOUR
(5) }, /* USSR Zone 4 */
475 { "ist", tZONE
, -HOUR
(5.5) },/* Indian Standard */
477 { "zp6", tZONE
, -HOUR
(6) }, /* USSR Zone 5 */
479 /* For completeness. NST is also Newfoundland Stanard, and SST is
480 * also Swedish Summer. */
481 { "nst", tZONE
, -HOUR
(6.5) },/* North Sumatra */
482 { "sst", tZONE
, -HOUR
(7) }, /* South Sumatra, USSR Zone 6 */
484 { "wast", tZONE
, -HOUR
(7) }, /* West Australian Standard */
485 { "wadt", tDAYZONE
, -HOUR
(7) }, /* West Australian Daylight */
487 { "jt", tZONE
, -HOUR
(7.5) },/* Java (3pm in Cronusland!) */
489 { "cct", tZONE
, -HOUR
(8) }, /* China Coast, USSR Zone 7 */
490 { "jst", tZONE
, -HOUR
(9) }, /* Japan Standard, USSR Zone 8 */
492 { "cast", tZONE
, -HOUR
(9.5) },/* Central Australian Standard */
493 { "cadt", tDAYZONE
, -HOUR
(9.5) },/* Central Australian Daylight */
495 { "east", tZONE
, -HOUR
(10) }, /* Eastern Australian Standard */
496 { "eadt", tDAYZONE
, -HOUR
(10) }, /* Eastern Australian Daylight */
497 { "gst", tZONE
, -HOUR
(10) }, /* Guam Standard, USSR Zone 9 */
498 { "nzt", tZONE
, -HOUR
(12) }, /* New Zealand */
499 { "nzst", tZONE
, -HOUR
(12) }, /* New Zealand Standard */
500 { "nzdt", tDAYZONE
, -HOUR
(12) }, /* New Zealand Daylight */
501 { "idle", tZONE
, -HOUR
(12) }, /* International Date Line East */
505 /* Military timezone table. */
506 static TABLE
const MilitaryTable
[] = {
507 { "a", tZONE
, HOUR
( 1) },
508 { "b", tZONE
, HOUR
( 2) },
509 { "c", tZONE
, HOUR
( 3) },
510 { "d", tZONE
, HOUR
( 4) },
511 { "e", tZONE
, HOUR
( 5) },
512 { "f", tZONE
, HOUR
( 6) },
513 { "g", tZONE
, HOUR
( 7) },
514 { "h", tZONE
, HOUR
( 8) },
515 { "i", tZONE
, HOUR
( 9) },
516 { "k", tZONE
, HOUR
( 10) },
517 { "l", tZONE
, HOUR
( 11) },
518 { "m", tZONE
, HOUR
( 12) },
519 { "n", tZONE
, HOUR
(- 1) },
520 { "o", tZONE
, HOUR
(- 2) },
521 { "p", tZONE
, HOUR
(- 3) },
522 { "q", tZONE
, HOUR
(- 4) },
523 { "r", tZONE
, HOUR
(- 5) },
524 { "s", tZONE
, HOUR
(- 6) },
525 { "t", tZONE
, HOUR
(- 7) },
526 { "u", tZONE
, HOUR
(- 8) },
527 { "v", tZONE
, HOUR
(- 9) },
528 { "w", tZONE
, HOUR
(-10) },
529 { "x", tZONE
, HOUR
(-11) },
530 { "y", tZONE
, HOUR
(-12) },
531 { "z", tZONE
, HOUR
( 0) },
548 ToSeconds
(Hours
, Minutes
, Seconds
, Meridian
)
554 if
(Minutes
< 0 || Minutes
> 59 || Seconds
< 0 || Seconds
> 59)
558 if
(Hours
< 0 || Hours
> 23)
560 return
(Hours
* 60L + Minutes
) * 60L + Seconds
;
562 if
(Hours
< 1 || Hours
> 12)
566 return
(Hours
* 60L + Minutes
) * 60L + Seconds
;
568 if
(Hours
< 1 || Hours
> 12)
572 return
((Hours
+ 12) * 60L + Minutes
) * 60L + Seconds
;
581 * A negative number, which means to use its absolute value (why?)
582 * A number from 0 to 99, which means a year from 1900 to 1999, or
583 * The actual year (>=100). */
585 Convert
(Month
, Day
, Year
, Hours
, Minutes
, Seconds
, Meridian
, DSTmode
)
595 static int DaysInMonth
[12] = {
596 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
608 DaysInMonth
[1] = Year %
4 == 0 && (Year %
100 != 0 || Year %
400 == 0)
610 /* Checking for 2038 bogusly assumes that time_t is 32 bits. But
611 I'm too lazy to try to check for time_t overflow in another way. */
612 if
(Year
< EPOCH || Year
> 2038
613 || Month
< 1 || Month
> 12
614 /* Lint fluff: "conversion from long may lose accuracy" */
615 || Day
< 1 || Day
> DaysInMonth
[(int)--Month
])
618 for
(Julian
= Day
- 1, i
= 0; i
< Month
; i
++)
619 Julian
+= DaysInMonth
[i
];
620 for
(i
= EPOCH
; i
< Year
; i
++)
621 Julian
+= 365 + (i %
4 == 0);
622 Julian
*= SECSPERDAY
;
623 Julian
+= yyTimezone
* 60L;
624 if
((tod
= ToSeconds
(Hours
, Minutes
, Seconds
, Meridian
)) < 0)
628 ||
(DSTmode
== DSTmaybe
&& localtime
(&Julian
)->tm_isdst
))
635 DSTcorrect
(Start
, Future
)
642 StartDay
= (localtime
(&Start
)->tm_hour
+ 1) %
24;
643 FutureDay
= (localtime
(&Future
)->tm_hour
+ 1) %
24;
644 return
(Future
- Start
) + (StartDay
- FutureDay
) * 60L * 60L;
649 RelativeDate
(Start
, DayOrdinal
, DayNumber
)
658 tm
= localtime
(&now
);
659 now
+= SECSPERDAY
* ((DayNumber
- tm
->tm_wday
+ 7) %
7);
660 now
+= 7 * SECSPERDAY
* (DayOrdinal
<= 0 ? DayOrdinal
: DayOrdinal
- 1);
661 return DSTcorrect
(Start
, now
);
666 RelativeMonth
(Start
, RelMonth
)
676 tm
= localtime
(&Start
);
677 Month
= 12 * (tm
->tm_year
+ 1900) + tm
->tm_mon
+ RelMonth
;
679 Month
= Month %
12 + 1;
680 return DSTcorrect
(Start
,
681 Convert
(Month
, (time_t)tm
->tm_mday
, Year
,
682 (time_t)tm
->tm_hour
, (time_t)tm
->tm_min
, (time_t)tm
->tm_sec
,
693 register
const TABLE
*tp
;
697 /* Make it lowercase. */
698 for
(p
= buff
; *p
; p
++)
702 if
(strcmp
(buff
, "am") == 0 || strcmp
(buff
, "a.m.") == 0) {
703 yylval.Meridian
= MERam
;
706 if
(strcmp
(buff
, "pm") == 0 || strcmp
(buff
, "p.m.") == 0) {
707 yylval.Meridian
= MERpm
;
711 /* See if we have an abbreviation for a month. */
712 if
(strlen
(buff
) == 3)
714 else if
(strlen
(buff
) == 4 && buff
[3] == '.') {
721 for
(tp
= MonthDayTable
; tp
->name
; tp
++) {
723 if
(strncmp
(buff
, tp
->name
, 3) == 0) {
724 yylval.Number
= tp
->value
;
728 else if
(strcmp
(buff
, tp
->name
) == 0) {
729 yylval.Number
= tp
->value
;
734 for
(tp
= TimezoneTable
; tp
->name
; tp
++)
735 if
(strcmp
(buff
, tp
->name
) == 0) {
736 yylval.Number
= tp
->value
;
740 if
(strcmp
(buff
, "dst") == 0)
743 for
(tp
= UnitsTable
; tp
->name
; tp
++)
744 if
(strcmp
(buff
, tp
->name
) == 0) {
745 yylval.Number
= tp
->value
;
749 /* Strip off any plural and try the units table again. */
750 i
= strlen
(buff
) - 1;
751 if
(buff
[i
] == 's') {
753 for
(tp
= UnitsTable
; tp
->name
; tp
++)
754 if
(strcmp
(buff
, tp
->name
) == 0) {
755 yylval.Number
= tp
->value
;
758 buff
[i
] = 's'; /* Put back for "this" in OtherTable. */
761 for
(tp
= OtherTable
; tp
->name
; tp
++)
762 if
(strcmp
(buff
, tp
->name
) == 0) {
763 yylval.Number
= tp
->value
;
767 /* Military timezones. */
768 if
(buff
[1] == '\0' && isalpha
(*buff
)) {
769 for
(tp
= MilitaryTable
; tp
->name
; tp
++)
770 if
(strcmp
(buff
, tp
->name
) == 0) {
771 yylval.Number
= tp
->value
;
776 /* Drop out any periods and try the timezone table again. */
777 for
(i
= 0, p
= q
= buff
; *q
; q
++)
784 for
(tp
= TimezoneTable
; tp
->name
; tp
++)
785 if
(strcmp
(buff
, tp
->name
) == 0) {
786 yylval.Number
= tp
->value
;
804 while
(isspace
(*yyInput
))
807 if
(isdigit
(c
= *yyInput
) || c
== '-' || c
== '+') {
808 if
(c
== '-' || c
== '+') {
809 sign
= c
== '-' ?
-1 : 1;
810 if
(!isdigit
(*++yyInput
))
811 /* skip the '-' sign */
816 for
(yylval.Number
= 0; isdigit
(c
= *yyInput
++); )
817 yylval.Number
= 10 * yylval.Number
+ c
- '0';
820 yylval.Number
= -yylval.Number
;
821 return sign ? tSNUMBER
: tUNUMBER
;
824 for
(p
= buff
; isalpha
(c
= *yyInput
++) || c
== '.'; )
825 if
(p
< &buff
[sizeof buff
- 1])
829 return LookupWord
(buff
);
846 #define TM_YEAR_ORIGIN 1900
848 /* Yield A - B, measured in seconds. */
853 int ay
= a
->tm_year
+ (TM_YEAR_ORIGIN
- 1);
854 int by
= b
->tm_year
+ (TM_YEAR_ORIGIN
- 1);
856 /* difference in day of year */
857 a
->tm_yday
- b
->tm_yday
858 /* + intervening leap days */
859 + ((ay
>> 2) - (by
>> 2))
861 + ((ay
/100 >> 2) - (by
/100 >> 2))
862 /* + difference in years * 365 */
863 + (long)(ay
-by
) * 365
865 return
(60*(60*(24*days
+ (a
->tm_hour
- b
->tm_hour
))
866 + (a
->tm_min
- b
->tm_min
))
867 + (a
->tm_sec
- b
->tm_sec
));
886 (void)time
(&nowtime
);
888 gmt_ptr
= gmtime
(&nowtime
);
891 /* Make a copy, in case localtime modifies *tm (I think
892 that comment now applies to *gmt_ptr, but I am too
893 lazy to dig into how gmtime and locatime allocate the
894 structures they return pointers to). */
898 if
(! (tm
= localtime
(&nowtime
)))
902 ftz.timezone
= difftm
(&gmt
, tm
) / 60;
904 /* We are on a system like VMS, where the system clock is
905 in local time and the system has no concept of timezones.
906 Hopefully we can fake this out (for the case in which the
907 user specifies no timezone) by just saying the timezone
919 tm
= localtime
(&nowtime
);
920 yyYear
= tm
->tm_year
+ 1900;
921 yyMonth
= tm
->tm_mon
+ 1;
923 yyTimezone
= now
->timezone
;
924 yyDSTmode
= DSTmaybe
;
938 || yyHaveTime
> 1 || yyHaveZone
> 1 || yyHaveDate
> 1 || yyHaveDay
> 1)
941 if
(yyHaveDate || yyHaveTime || yyHaveDay
) {
942 Start
= Convert
(yyMonth
, yyDay
, yyYear
, yyHour
, yyMinutes
, yySeconds
,
943 yyMeridian
, yyDSTmode
);
950 Start
-= ((tm
->tm_hour
* 60L + tm
->tm_min
) * 60L) + tm
->tm_sec
;
953 Start
+= yyRelSeconds
;
954 Start
+= RelativeMonth
(Start
, yyRelMonth
);
956 if
(yyHaveDay
&& !yyHaveDate
) {
957 tod
= RelativeDate
(Start
, yyDayOrdinal
, yyDayNumber
);
961 /* Have to do *something* with a legitimate -1 so it's distinguishable
962 * from the error return value. (Alternately could set errno on error.) */
963 return Start
== -1 ?
0 : Start
;
978 (void)printf
("Enter date, or blank line to exit.\n\t> ");
979 (void)fflush
(stdout
);
980 while
(gets
(buff
) && buff
[0]) {
981 d
= get_date
(buff
, (struct timeb
*)NULL
);
983 (void)printf
("Bad format - couldn't convert.\n");
985 (void)printf
("%s", ctime
(&d
));
986 (void)printf
("\t> ");
987 (void)fflush
(stdout
);
992 #endif /* defined(TEST) */