

In article <[email-masked]> [email-masked] (Stuart Cracraft) writes:
>
>Does anyone have a perl module or subroutine which parses
>a free-format date/time string such as input by a person
>
>	1-Jun-92 noon
>	2-Jan-85 00:05pm
>	5pm Apr 90 midnight
>	...etc.
>
>And returns either a long() representing the number of seconds
>since the epoch or a structure similar to that made by localtime() ?
>
>Thanks,
>Stuart

Here is the famous (or infamous) getdate routine adapted for use with
PERL. (This was a quick hack but, it is being used in a couple of
programs and no problems have shown up yet. 8-{)

Calling sequence:
  seconds = &getdate(date_time_str, 
                     time_in_seconds, 
                     offset_from_GMT_in_minutes);

time_in_seconds and offset_from_GMT_in_minutes are optional arguments.
If time_in_seconds is not specified then the current time is used.
If offset_from_GMT_in_minutes is not specified then TZ is read from the
environment to get the offset.

Examples of use:
  require 'getdate.pl';
  seconds = &getdate('Apr 24 17:44');
  seconds = &getdate('2 Feb 1992 03:53:17');
  ... many more date/time formats supported ...

Included in the following shar file are getdate.pl and getdate.y.
getdate.pl was generated from getdate.y by a version of Berkeley Yacc
1.8 that I modified to generate PERL output. (The patches are based on
Ray Lischner's patches to byacc 1.6.) If anyone would like a copy of
the patches I can e-mail them or make them available for anonymous FTP
if there is enough interest.

================= cut here ====================
#! /bin/sh
# This is a shell archive.  Remove anything before this line, then feed it
# into a shell via "sh file" or similar.  To overwrite existing files,
# type "sh file -c".
# The tool that generated this appeared in the comp.sources.unix newsgroup;
# send mail to [email-masked] if you want that tool.
# Contents:  getdate.pl getdate.y
# Wrapped by rick@peppy on Fri Jun 26 08:04:12 1992
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
echo If this archive is complete, you will see the following message:
echo '          "shar: End of archive 1 (of 1)."'
if test -f 'getdate.pl' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'getdate.pl'\"
else
  echo shar: Extracting \"'getdate.pl'\" \(28029 characters\)
  sed "s/^X//" >'getdate.pl' <<'END_OF_FILE'
X$yysccsid = "@(#)yaccpar	1.8 (Berkeley) 01/20/91 (Perl 2.0 04/23/92)";
X#define YYBYACC 1
X;# 	Steven M. Bellovin (unc!smb)
X;#	Dept. of Computer Science
X;#	University of North Carolina at Chapel Hill
X;#	@(#)getdate.y	2.13	9/16/86
X;#
X;#	Richard J. Ohnemus ([email-masked])
X;#	(Where do I work??? I'm not even sure who I am! 8-{)
X;#	converted to PERL 4/24/92
X
Xpackage getdate;
X
X$daysec = 24 * 60 * 60;
X
X$AM = 1;
X$PM = 2;
X$DAYLIGHT = 1;
X$STANDARD = 2;
X$MAYBE = 3;
X
X$ID=257;
X$MONTH=258;
X$DAY=259;
X$MERIDIAN=260;
X$NUMBER=261;
X$UNIT=262;
X$MUNIT=263;
X$SUNIT=264;
X$ZONE=265;
X$DAYZONE=266;
X$AGO=267;
X$YYERRCODE=256;
X@yylhs = split(' ', '                                    -1
X     0     0     1     1     1     1     1     1     7     2
X     2     2     2     2     2     2     3     3     5     5
X     5     4     4     4     4     4     4     4     4     6
X     6     6     6     6     6     6', 37);
X@yylen = split(' ', '                                     2
X     0     2     1     1     1     1     1     1     1     2
X     3     4     4     5     6     6     1     1     1     2
X     2     3     5     2     4     5     3     2     3     2
X     2     2     1     1     1     2', 37);
X@yydefred = split(' ', '                                  1
X     0     0     0     0    33    34    35    17    18     2
X     3     4     5     6     0     8     0    20     0    21
X    10    30    31    32     0     0    36     0     0    29
X     0     0     0    25    12    13     0     0    26     0
X    23    15    16', 44);
X@yydgoto = split(' ', '                                   1
X    10    11    12    13    14    15    16', 8);
X@yysindex = split(' ', '                                  0
X  -241  -255   -37   -47     0     0     0     0     0     0
X     0     0     0     0  -259     0   -42     0  -252     0
X     0     0     0     0  -249  -248     0   -44  -246     0
X   -55   -31  -235     0     0     0  -234  -232     0  -256
X     0     0     0', 44);
X@yyrindex = split(' ', '                                  0
X     0     0     1    70     0     0     0     0     0     0
X     0     0     0     0    10     0    37     0    46     0
X     0     0     0     0     0     0     0    19     0     0
X    55    28     0     0     0     0     0     0     0    64
X     0     0     0', 44);
X@yygindex = split(' ', '                                  0
X     0     0     0     0     0     0     0', 8);
X$YYTABLESIZE=336;
X@yytable = split(' ', '                                  26
X    19    29    37    42    43    17    18    27    30     7
X    25    31    32    33    34    38     2     3    27     4
X     5     6     7     8     9    39    40    22    41     0
X     0     0     0     0     0     0    24     0     0     0
X     0     0     0     0     0    28     0     0     0     0
X     0     0     0     0    11     0     0     0     0     0
X     0     0     0    14     0     0     0     0     0     9
X     0     0     0     0     0     0     0     0     0     0
X     0     0     0     0     0     0     0     0     0     0
X     0     0     0     0     0     0     0     0     0     0
X     0     0     0     0     0     0     0     0     0     0
X     0     0     0     0     0     0     0     0     0     0
X     0     0     0     0     0     0     0     0     0     0
X     0     0     0     0     0     0     0     0     0     0
X     0     0     0     0     0     0     0     0     0     0
X     0     0     0     0     0     0     0     0     0     0
X     0     0     0     0     0     0     0     0     0     0
X     0     0     0     0     0     0     0     0     0     0
X     0     0     0     0     0     0     0     0     0     0
X     0     0     0     0     0     0     0     0     0     0
X     0     0     0     0    35    36     0     0     0     0
X    19    20    21     0    22    23    24     0    28     0
X     0     0     0     0     0     0     0     0     0     0
X     0     0     0     0     0     0     0     0     0     0
X     0     0     0     0     0     0     0     0     0     0
X     0     0     0     0     0     0     0     0    19    19
X     0    19    19    19    19    19    19     7     7     0
X     7     7     7     7     7     7    27    27     0    27
X    27    27    27    27    27    22    22     0    22    22
X    22    22    22    22    24    24     0     0    24    24
X    24    24    24    28    28     0     0    28    28    28
X    28    28    11    11     0     0    11    11    11    11
X    11    14    14     0     0    14    14    14    14    14
X     9     0     0     0     9     9', 337);
X@yycheck = split(' ', '                                  47
X     0    44    58   260   261   261    44   267   261     0
X    58   261   261    58   261    47   258   259     0   261
X   262   263   264   265   266   261   261     0   261    -1
X    -1    -1    -1    -1    -1    -1     0    -1    -1    -1
X    -1    -1    -1    -1    -1     0    -1    -1    -1    -1
X    -1    -1    -1    -1     0    -1    -1    -1    -1    -1
X    -1    -1    -1     0    -1    -1    -1    -1    -1     0
X    -1    -1    -1    -1    -1    -1    -1    -1    -1    -1
X    -1    -1    -1    -1    -1    -1    -1    -1    -1    -1
X    -1    -1    -1    -1    -1    -1    -1    -1    -1    -1
X    -1    -1    -1    -1    -1    -1    -1    -1    -1    -1
X    -1    -1    -1    -1    -1    -1    -1    -1    -1    -1
X    -1    -1    -1    -1    -1    -1    -1    -1    -1    -1
X    -1    -1    -1    -1    -1    -1    -1    -1    -1    -1
X    -1    -1    -1    -1    -1    -1    -1    -1    -1    -1
X    -1    -1    -1    -1    -1    -1    -1    -1    -1    -1
X    -1    -1    -1    -1    -1    -1    -1    -1    -1    -1
X    -1    -1    -1    -1    -1    -1    -1    -1    -1    -1
X    -1    -1    -1    -1    -1    -1    -1    -1    -1    -1
X    -1    -1    -1    -1    -1    -1    -1    -1    -1    -1
X    -1    -1    -1    -1   260   261    -1    -1    -1    -1
X   258   259   260    -1   262   263   264    -1   261    -1
X    -1    -1    -1    -1    -1    -1    -1    -1    -1    -1
X    -1    -1    -1    -1    -1    -1    -1    -1    -1    -1
X    -1    -1    -1    -1    -1    -1    -1    -1    -1    -1
X    -1    -1    -1    -1    -1    -1    -1    -1   258   259
X    -1   261   262   263   264   265   266   258   259    -1
X   261   262   263   264   265   266   258   259    -1   261
X   262   263   264   265   266   258   259    -1   261   262
X   263   264   265   266   258   259    -1    -1   262   263
X   264   265   266   258   259    -1    -1   262   263   264
X   265   266   258   259    -1    -1   262   263   264   265
X   266   258   259    -1    -1   262   263   264   265   266
X   261    -1    -1    -1   265   266', 337);
X$YYFINAL=1;
X#ifndef YYDEBUG
X#define YYDEBUG 0
X#endif
X$YYMAXTOKEN=267;
X#if YYDEBUG
X@yyname = (
X"end-of-file",'','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','',
X'','','','','','','','','','',"','",'','',"'/'",'','','','','','','','','','',"':'",'','','','','','','','','',
X'','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','',
X'','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','',
X'','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','',
X'','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','',
X'','','','','','','','','','','','','','','','','','','','','','','','','','','','','',"ID","MONTH","DAY",
X"MERIDIAN","NUMBER","UNIT","MUNIT","SUNIT","ZONE","DAYZONE","AGO",
X);
X@yyrule = (
X"$accept : timedate",
X"timedate :",
X"timedate : timedate item",
X"item : tspec",
X"item : zone",
X"item : dtspec",
X"item : dyspec",
X"item : rspec",
X"item : nspec",
X"nspec : NUMBER",
X"tspec : NUMBER MERIDIAN",
X"tspec : NUMBER ':' NUMBER",
X"tspec : NUMBER ':' NUMBER MERIDIAN",
X"tspec : NUMBER ':' NUMBER NUMBER",
X"tspec : NUMBER ':' NUMBER ':' NUMBER",
X"tspec : NUMBER ':' NUMBER ':' NUMBER MERIDIAN",
X"tspec : NUMBER ':' NUMBER ':' NUMBER NUMBER",
X"zone : ZONE",
X"zone : DAYZONE",
X"dyspec : DAY",
X"dyspec : DAY ','",
X"dyspec : NUMBER DAY",
X"dtspec : NUMBER '/' NUMBER",
X"dtspec : NUMBER '/' NUMBER '/' NUMBER",
X"dtspec : MONTH NUMBER",
X"dtspec : MONTH NUMBER ',' NUMBER",
X"dtspec : MONTH NUMBER NUMBER ':' NUMBER",
X"dtspec : MONTH NUMBER NUMBER",
X"dtspec : NUMBER MONTH",
X"dtspec : NUMBER MONTH NUMBER",
X"rspec : NUMBER UNIT",
X"rspec : NUMBER MUNIT",
X"rspec : NUMBER SUNIT",
X"rspec : UNIT",
X"rspec : MUNIT",
X"rspec : SUNIT",
X"rspec : rspec AGO",
X);
X#endif
Xsub yyclearin { $yychar = -1; }
Xsub yyerrok { $yyerrflag = 0; }
X$YYSTACKSIZE = $YYSTACKSIZE || $YYMAXDEPTH || 500;
X$YYMAXDEPTH = $YYMAXDEPTH || $YYSTACKSIZE || 500;
X$yyss[$YYSTACKSIZE] = 0;
X$yyvs[$YYSTACKSIZE] = 0;
Xsub YYERROR { ++$yynerrs; &yy_err_recover; }
Xsub yy_err_recover
X{
X  if ($yyerrflag < 3)
X  {
X    $yyerrflag = 3;
X    while (1)
X    {
X      if (($yyn = $yysindex[$yyss[$yyssp]]) && 
X          ($yyn += $YYERRCODE) >= 0 && 
X          $yycheck[$yyn] == $YYERRCODE)
X      {
X#if YYDEBUG
X       print "yydebug: state $yyss[$yyssp], error recovery shifting",
X             " to state $yytable[$yyn]\n" if $yydebug;
X#endif
X        $yyss[++$yyssp] = $yystate = $yytable[$yyn];
X        $yyvs[++$yyvsp] = $yylval;
X        next yyloop;
X      }
X      else
X      {
X#if YYDEBUG
X        print "yydebug: error recovery discarding state ",
X              $yyss[$yyssp], "\n"  if $yydebug;
X#endif
X        return(1) if $yyssp <= 0;
X        --$yyssp;
X        --$yyvsp;
X      }
X    }
X  }
X  else
X  {
X    return (1) if $yychar == 0;
X#if YYDEBUG
X    if ($yydebug)
X    {
X      $yys = '';
X      if ($yychar <= $YYMAXTOKEN) { $yys = $yyname[$yychar]; }
X      if (!$yys) { $yys = 'illegal-symbol'; }
X      print "yydebug: state $yystate, error recovery discards ",
X            "token $yychar ($yys)\n";
X    }
X#endif
X    $yychar = -1;
X    next yyloop;
X  }
X0;
X} # yy_err_recover
X
Xsub yyparse
X{
X#ifdef YYDEBUG
X  if ($yys = $ENV{'YYDEBUG'})
X  {
X    $yydebug = int($1) if $yys =~ /^(\d)/;
X  }
X#endif
X
X  $yynerrs = 0;
X  $yyerrflag = 0;
X  $yychar = (-1);
X
X  $yyssp = 0;
X  $yyvsp = 0;
X  $yyss[$yyssp] = $yystate = 0;
X
Xyyloop: while(1)
X  {
X    yyreduce: {
X      last yyreduce if ($yyn = $yydefred[$yystate]);
X      if ($yychar < 0)
X      {
X        if (($yychar = &yylex) < 0) { $yychar = 0; }
X#if YYDEBUG
X        if ($yydebug)
X        {
X          $yys = '';
X          if ($yychar <= $#yyname) { $yys = $yyname[$yychar]; }
X          if (!$yys) { $yys = 'illegal-symbol'; };
X          print "yydebug: state $yystate, reading $yychar ($yys)\n";
X        }
X#endif
X      }
X      if (($yyn = $yysindex[$yystate]) && ($yyn += $yychar) >= 0 &&
X              $yycheck[$yyn] == $yychar)
X      {
X#if YYDEBUG
X        print "yydebug: state $yystate, shifting to state ",
X              $yytable[$yyn], "\n"  if $yydebug;
X#endif
X        $yyss[++$yyssp] = $yystate = $yytable[$yyn];
X        $yyvs[++$yyvsp] = $yylval;
X        $yychar = (-1);
X        --$yyerrflag if $yyerrflag > 0;
X        next yyloop;
X      }
X      if (($yyn = $yyrindex[$yystate]) && ($yyn += $yychar) >= 0 &&
X            $yycheck[$yyn] == $yychar)
X      {
X        $yyn = $yytable[$yyn];
X        last yyreduce;
X      }
X      if (! $yyerrflag) {
X        &yyerror('syntax error');
X        ++$yynerrs;
X      }
X      return(1) if &yy_err_recover;
X    } # yyreduce
X#if YYDEBUG
X    print "yydebug: state $yystate, reducing by rule ",
X          "$yyn ($yyrule[$yyn])\n"  if $yydebug;
X#endif
X    $yym = $yylen[$yyn];
X    $yyval = $yyvs[$yyvsp+1-$yym];
X    switch:
X    {
Xif ($yyn == 3) {
X
X		{
X		    $timeflag++;
X		
Xlast switch;
X} }
Xif ($yyn == 4) {
X
X		{
X		    $zoneflag++;
X		
Xlast switch;
X} }
Xif ($yyn == 5) {
X
X		{
X		    $dateflag++;
X		
Xlast switch;
X} }
Xif ($yyn == 6) {
X
X		{
X		    $dayflag++;
X		
Xlast switch;
X} }
Xif ($yyn == 7) {
X
X		{
X		    $relflag++;
X		
Xlast switch;
X} }
Xif ($yyn == 9) {
X
X		{
X		    if ($timeflag && $dateflag && !$relflag) {
X			$year = $yyvs[$yyvsp-0];
X		    }
X		    else {
X			$timeflag++;
X			$hh = $yyvs[$yyvsp-0] / 100;
X			$mm = $yyvs[$yyvsp-0] % 100;
X			$ss = 0;
X			$merid = 24;
X		    }
X		
Xlast switch;
X} }
Xif ($yyn == 10) {
X
X		{
X		    $hh = $yyvs[$yyvsp-1];
X		    $mm = 0;
X		    $ss = 0;
X		    $merid = $yyvs[$yyvsp-0];
X		
Xlast switch;
X} }
Xif ($yyn == 11) {
X
X		{
X		    $hh = $yyvs[$yyvsp-2];
X		    $mm = $yyvs[$yyvsp-0];
X		    $merid = 24;
X		
Xlast switch;
X} }
Xif ($yyn == 12) {
X
X		{
X		    $hh = $yyvs[$yyvsp-3];
X		    $mm = $yyvs[$yyvsp-1];
X		    $merid = $yyvs[$yyvsp-0];
X		
Xlast switch;
X} }
Xif ($yyn == 13) {
X
X		{
X		    $hh = $yyvs[$yyvsp-3];
X		    $mm = $yyvs[$yyvsp-1];
X		    $merid = 24;
X		    $daylight = $STANDARD;
X		    $ourzone = $yyvs[$yyvsp-0] % 100 + 60 * $yyvs[$yyvsp-0] / 100;
X		
Xlast switch;
X} }
Xif ($yyn == 14) {
X
X		{
X		    $hh = $yyvs[$yyvsp-4];
X		    $mm = $yyvs[$yyvsp-2];
X		    $ss = $yyvs[$yyvsp-0];
X		    $merid = 24;
X		
Xlast switch;
X} }
Xif ($yyn == 15) {
X
X		{
X		    $hh = $yyvs[$yyvsp-5];
X		    $mm = $yyvs[$yyvsp-3];
X		    $ss = $yyvs[$yyvsp-1];
X		    $merid = $yyvs[$yyvsp-0];
X		
Xlast switch;
X} }
Xif ($yyn == 16) {
X
X		{
X		    $hh = $yyvs[$yyvsp-5];
X		    $mm = $yyvs[$yyvsp-3];
X		    $ss = $yyvs[$yyvsp-1];
X		    $merid = 24;
X		    $daylight = $STANDARD;
X		    $ourzone = $yyvs[$yyvsp-0] % 100 + 60 * $yyvs[$yyvsp-0] / 100;
X		
Xlast switch;
X} }
Xif ($yyn == 17) {
X
X		{
X		    $ourzone = $yyvs[$yyvsp-0];
X		    $daylight = $STANDARD;
X		
Xlast switch;
X} }
Xif ($yyn == 18) {
X
X		{
X		    $ourzone = $yyvs[$yyvsp-0];
X		    $daylight = $DAYLIGHT;
X		
Xlast switch;
X} }
Xif ($yyn == 19) {
X
X		{
X		    $dayord = 1;
X		    $dayreq = $yyvs[$yyvsp-0];
X		
Xlast switch;
X} }
Xif ($yyn == 20) {
X
X		{
X		    $dayord = 1;
X		    $dayreq = $yyvs[$yyvsp-1];
X		
Xlast switch;
X} }
Xif ($yyn == 21) {
X
X		{
X		    $dayord = $yyvs[$yyvsp-1];
X		    $dayreq = $yyvs[$yyvsp-0];
X		
Xlast switch;
X} }
Xif ($yyn == 22) {
X
X		{
X		    $month = $yyvs[$yyvsp-2];
X		    $day = $yyvs[$yyvsp-0];
X		
Xlast switch;
X} }
Xif ($yyn == 23) {
X
X		{
X		    #
X;# 		     * HACK ALERT!!!!
X;# 		     * The 1000 is a magic number to attempt to force
X;# 		     * use of 4 digit years if year/month/day can be
X;# 		     * parsed. This was only done for backwards
X;# 		     * compatibility in rh.
X;# 		     
X
X		    if ($yyvs[$yyvsp-4] > 1000) {
X			$year = $yyvs[$yyvsp-4];
X			$month = $yyvs[$yyvsp-2];
X			$day = $yyvs[$yyvsp-0];
X		    }
X		    else {
X			$month = $yyvs[$yyvsp-4];
X			$day = $yyvs[$yyvsp-2];
X			$year = $yyvs[$yyvsp-0];
X		    }
X		
Xlast switch;
X} }
Xif ($yyn == 24) {
X
X		{
X		    $month = $yyvs[$yyvsp-1];
X		    $day = $yyvs[$yyvsp-0];
X		
Xlast switch;
X} }
Xif ($yyn == 25) {
X
X		{
X		    $month = $yyvs[$yyvsp-3];
X		    $day = $yyvs[$yyvsp-2];
X		    $year = $yyvs[$yyvsp-0];
X		
Xlast switch;
X} }
Xif ($yyn == 26) {
X
X		{
X		    $month = $yyvs[$yyvsp-4];
X		    $day = $yyvs[$yyvsp-3];
X		    $hh = $yyvs[$yyvsp-2];
X		    $mm = $yyvs[$yyvsp-0];
X		    $merid = 24;
X		    $timeflag++;
X		
Xlast switch;
X} }
Xif ($yyn == 27) {
X
X		{
X		    $month = $yyvs[$yyvsp-2];
X		    $day = $yyvs[$yyvsp-1];
X		    $year = $yyvs[$yyvsp-0];
X		
Xlast switch;
X} }
Xif ($yyn == 28) {
X
X		{
X		    $month = $yyvs[$yyvsp-0];
X		    $day = $yyvs[$yyvsp-1];
X		
Xlast switch;
X} }
Xif ($yyn == 29) {
X
X		{
X		    $month = $yyvs[$yyvsp-1];
X		    $day = $yyvs[$yyvsp-2];
X		    $year = $yyvs[$yyvsp-0];
X		
Xlast switch;
X} }
Xif ($yyn == 30) {
X
X		{
X		    $relsec +=  60 * $yyvs[$yyvsp-1] * $yyvs[$yyvsp-0];
X		
Xlast switch;
X} }
Xif ($yyn == 31) {
X
X		{
X		    $relmonth += $yyvs[$yyvsp-1] * $yyvs[$yyvsp-0];
X		
Xlast switch;
X} }
Xif ($yyn == 32) {
X
X		{
X		    $relsec += $yyvs[$yyvsp-1];
X		
Xlast switch;
X} }
Xif ($yyn == 33) {
X
X		{
X		    $relsec +=  60 * $yyvs[$yyvsp-0];
X		
Xlast switch;
X} }
Xif ($yyn == 34) {
X
X		{
X		    $relmonth += $yyvs[$yyvsp-0];
X		
Xlast switch;
X} }
Xif ($yyn == 35) {
X
X		{
X		    $relsec++;
X		
Xlast switch;
X} }
Xif ($yyn == 36) {
X
X		{
X		    $relsec = -$relsec;
X		    $relmonth = -$relmonth;
X		
Xlast switch;
X} }
X    } # switch
X    $yyssp -= $yym;
X    $yystate = $yyss[$yyssp];
X    $yyvsp -= $yym;
X    $yym = $yylhs[$yyn];
X    if ($yystate == 0 && $yym == 0)
X    {
X#if YYDEBUG
X      print "yydebug: after reduction, shifting from state 0 ",
X            "to state $YYFINAL\n" if $yydebug;
X#endif
X      $yystate = $YYFINAL;
X      $yyss[++$yyssp] = $YYFINAL;
X      $yyvs[++$yyvsp] = $yyval;
X      if ($yychar < 0)
X      {
X        if (($yychar = &yylex) < 0) { $yychar = 0; }
X#if YYDEBUG
X        if ($yydebug)
X        {
X          $yys = '';
X          if ($yychar <= $#yyname) { $yys = $yyname[$yychar]; }
X          if (!$yys) { $yys = 'illegal-symbol'; }
X          print "yydebug: state $YYFINAL, reading $yychar ($yys)\n";
X        }
X#endif
X      }
X      return(0) if $yychar == 0;
X      next yyloop;
X    }
X    if (($yyn = $yygindex[$yym]) && ($yyn += $yystate) >= 0 &&
X        $yyn <= $#yycheck && $yycheck[$yyn] == $yystate)
X    {
X        $yystate = $yytable[$yyn];
X    } else {
X        $yystate = $yydgoto[$yym];
X    }
X#if YYDEBUG
X    print "yydebug: after reduction, shifting from state ",
X        "$yyss[$yyssp] to state $yystate\n" if $yydebug;
X#endif
X    $yyss[++$yyssp] = $yystate;
X    $yyvs[++$yyvsp] = $yyval;
X  } # yyloop
X} # yyparse
X
X@mdays = (31, 0, 31,  30, 31, 30,  31, 31, 30,  31, 30, 31);
X$epoch = 1970;
X
Xsub dateconv
X{
X    local($mm, $dd, $yy, $h, $m, $s, $mer, $zone, $dayflag) = @_;
X    local($time_of_day, $jdate);
X    local($i);
X
X    if ($yy < 0) {
X	$yy = -$yy;
X    }
X    if ($yy < 100) {
X	$yy += 1900;
X    }
X    $mdays[1] =
X	28 + (($yy % 4) == 0 && (($yy % 100) != 0 || ($yy % 400) == 0));
X    if ($yy < $epoch || $yy > 2001 || $mm < 1 || $mm > 12
X	|| $dd < 1 || $dd > $mdays[--$mm]) {
X	return -1;
X    }
X    $jdate = $dd - 1;
X    for ($i = 0; $i < $mm; $i++) {
X	$jdate += $mdays[$i];
X    }
X    for ($i = $epoch; $i < $yy; $i++) {
X	$jdate += 365 + (($i % 4) == 0);
X    }
X    $jdate *= $daysec;
X    $jdate += $zone * 60;
X    if (($time_of_day = &timeconv($h, $m, $s, $mer)) < 0) {
X	return -1;
X    }
X    $jdate += $time_of_day;
X    if ($dayflag == $DAYLIGHT
X	|| ($dayflag == $MAYBE && (localtime($jdate))[8])) {
X	$jdate -= 60 * 60;
X    }
X    return $jdate;
X}
X
Xsub dayconv
X{
X    local($ordday, $day, $now) = @_;
X    local(@loctime);
X    local($time_of_day);
X
X    $time_of_day = $now;
X    @loctime = localtime($time_of_day);
X    $time_of_day += $daysec * (($day - $loctime[6] + 7) % 7);
X    $time_of_day += 7 * $daysec * ($ordday <= 0 ? $ordday : $ordday - 1);
X    return &daylcorr($time_of_day, $now);
X}
X
Xsub timeconv
X{
X    local($hh, $mm, $ss, $mer) = @_;
X
X    return -1 if ($mm < 0 || $mm > 59 || $ss < 0 || $ss > 59);
X
X    if ($mer == $AM) {
X	return -1 if ($hh < 1 || $hh > 12);
X	return 60 * (($hh % 12) * 60 + $mm) + $ss;
X    }
X    if ($mer == $PM) {
X	return -1 if ($hh < 1 || $hh > 12);
X	return 60 * (($hh % 12 + 12) * 60 + $mm) + $ss;
X    }
X    if ($mer == 24) {
X	return -1 if ($hh < 0 || $hh > 23);
X	return 60 * ($hh * 60 + $mm) + $ss;
X    }
X    return -1;
X}
X
Xsub monthadd
X{
X    local($sdate, $relmonth) = @_;
X    local(@ltime);
X    local($mm, $yy);
X    
X    return 0 if ($relmonth == 0);
X
X    @ltime = localtime(sdate);
X    $mm = 12 * $ltime[5] + $ltime[4] + $relmonth;
X    $yy = $mm / 12;
X    $mm = $mm % 12 + 1;
X    return &daylcorr(&dateconv($mm, $ltime[3], $yy, $ltime[2],
X			       $ltime[1], $ltime[0], 24, $ourzone, $MAYBE),
X		     $sdate);
X}
X
Xsub daylcorr
X{
X    local($future, $now) = @_;
X    local($fdayl, $nowdayl);		# int
X
X    $nowdayl = ((localtime($now))[2] + 1) % 24;
X    $fdayl = ((localtime($future))[2] + 1) % 24;
X    return ($future - $now) + 60 * 60 * ($nowdayl - $fdayl);
X}
X
Xsub yylex
X{
X    local($pcnt, $sign);
X
X    while (1) {
X	$dtstr =~ s/^\s*//;
X	
X	if ($dtstr =~ /^([-+])/) {
X	    $sign = ($1 eq '-') ? -1 : 1;
X	    $dtstr =~ s/^.//;
X	    if ($dtstr =~ /^(\d+)/) {
X		$yylval = eval "$1 * $sign";
X		$dtstr =~ s/^\d+//;
X		return $NUMBER;
X	    }
X	    else {
X		return &yylex;
X	    }
X	}
X	elsif ($dtstr =~ /^(\d+)/) {
X	    $yylval = eval "$1";
X	    $dtstr =~ s/^\d+//;
X	    return $NUMBER;
X	}
X	elsif ($dtstr =~ /^([a-zA-z][a-zA-Z.]*)/) {
X	    $dtstr = substr($dtstr, length($1));
X	    return &lookup($1);
X	}
X	elsif ($dtstr =~ /^\(/) {
X	    $pcnt = 0;
X	    do {
X		$dtstr = s/^(.)//;
X		return 0 if !defined($1);
X		$pcnt++ if ($1 eq '(');
X		$pcnt-- if ($1 eq ')');
X	    } while ($pcnt > 0);
X	}
X	else {
X	    $yylval = ord(substr($dtstr, 0, 1));
X	    $dtstr =~ s/^.//;
X	    return $yylval;
X	}
X    }
X}
X	
X
X%mdtab = (
X	  "January",	"$MONTH,1",
X	  "February",	"$MONTH,2",
X	  "March", 	"$MONTH,3",
X	  "April",	"$MONTH,4",
X	  "May",	"$MONTH,5",
X	  "June",	"$MONTH,6",
X	  "July",	"$MONTH,7",
X	  "August",	"$MONTH,8",
X	  "September",	"$MONTH,9",
X	  "Sept",	"$MONTH,9",
X	  "October",	"$MONTH,10",
X	  "November",	"$MONTH,11",
X	  "December",	"$MONTH,12",
X
X	  "Sunday",	"$DAY,0",
X	  "Monday",	"$DAY,1",
X	  "Tuesday",	"$DAY,2",
X	  "Tues",	"$DAY,2",
X	  "Wednesday",	"$DAY,3",
X	  "Wednes",	"$DAY,3",
X	  "Thursday",	"$DAY,4",
X	  "Thur",	"$DAY,4",
X	  "Thurs",	"$DAY,4",
X	  "Friday",	"$DAY,5",
X	  "Saturday",	"$DAY,6"
X	  );
X
X$HRS='*60';
X$HALFHR='30';
X
X%mztab = (
X	  "a.m.",	"$MERIDIAN,$AM",
X	  "am",		"$MERIDIAN,$AM",
X	  "p.m.",	"$MERIDIAN,$PM",
X	  "pm",		"$MERIDIAN,$PM",
X	  "nst",	"$ZONE,3 $HRS + $HALFHR",	# Newfoundland
X	  "n.s.t.",	"$ZONE,3 $HRS + $HALFHR",
X	  "ast",	"$ZONE,4 $HRS",			# Atlantic
X	  "a.s.t.",	"$ZONE,4 $HRS",
X	  "adt",	"$DAYZONE,4 $HRS",
X	  "a.d.t.",	"$DAYZONE,4 $HRS",
X	  "est",	"$ZONE,5 $HRS",			# Eastern
X	  "e.s.t.",	"$ZONE,5 $HRS",
X	  "edt",	"$DAYZONE,5 $HRS",
X	  "e.d.t.",	"$DAYZONE,5 $HRS",
X	  "cst",	"$ZONE,6 $HRS",			# Central
X	  "c.s.t.",	"$ZONE,6 $HRS",
X	  "cdt",	"$DAYZONE,6 $HRS",
X	  "c.d.t.",	"$DAYZONE,6 $HRS",
X	  "mst",	"$ZONE,7 $HRS",			# Mountain
X	  "m.s.t.",	"$ZONE,7 $HRS",
X	  "mdt",	"$DAYZONE,7 $HRS",
X	  "m.d.t.",	"$DAYZONE,7 $HRS",
X	  "pst",	"$ZONE,8 $HRS",			# Pacific
X	  "p.s.t.",	"$ZONE,8 $HRS",
X	  "pdt",	"$DAYZONE,8 $HRS",
X	  "p.d.t.",	"$DAYZONE,8 $HRS",
X	  "yst",	"$ZONE,9 $HRS",			# Yukon
X	  "y.s.t.",	"$ZONE,9 $HRS",
X	  "ydt",	"$DAYZONE,9 $HRS",
X	  "y.d.t.",	"$DAYZONE,9 $HRS",
X	  "hst",	"$ZONE,10 $HRS",		# Hawaii
X	  "h.s.t.",	"$ZONE,10 $HRS",
X	  "hdt",	"$DAYZONE,10 $HRS",
X	  "h.d.t.",	"$DAYZONE,10 $HRS",
X
X	  "gmt",	"$ZONE,0 $HRS",
X	  "g.m.t.",	"$ZONE,0 $HRS",
X	  "bst",	"$DAYZONE,0 $HRS",		# British Summer Time
X	  "b.s.t.",	"$DAYZONE,0 $HRS",
X	  "eet",	"$ZONE,0 $HRS",			# European Eastern Time
X	  "e.e.t.",	"$ZONE,0 $HRS",
X	  "eest",	"$DAYZONE,0 $HRS",		# European Eastern Summer Time
X	  "e.e.s.t.",	"$DAYZONE,0 $HRS",
X	  "met",	"$ZONE,-1 $HRS",		# Middle European Time
X	  "m.e.t.",	"$ZONE,-1 $HRS",
X	  "mest",	"$DAYZONE,-1 $HRS",		# Middle European Summer Time
X	  "m.e.s.t.",	"$DAYZONE,-1 $HRS",
X	  "wet",	"$ZONE,-2 $HRS ",		# Western European Time
X	  "w.e.t.",	"$ZONE,-2 $HRS ",
X	  "west",	"$DAYZONE,-2 $HRS",		# Western European Summer Time
X	  "w.e.s.t.",	"$DAYZONE,-2 $HRS",
X
X	  "jst",	"$ZONE,-9 $HRS",		# Japan Standard Time
X	  "j.s.t.",	"$ZONE,-9 $HRS",		# Japan Standard Time
X	  						# No daylight savings time
X
X	  "aest",	"$ZONE,-10 $HRS",		# Australian Eastern Time
X	  "a.e.s.t.",	"$ZONE,-10 $HRS",
X	  "aesst",	"$DAYZONE,-10 $HRS",		# Australian Eastern Summer Time
X	  "a.e.s.s.t.",	"$DAYZONE,-10 $HRS",
X	  "acst",	"$ZONE,-(9 $HRS + $HALFHR)",	# Australian Central Time
X	  "a.c.s.t.",	"$ZONE,-(9 $HRS + $HALFHR)",
X	  "acsst",	"$DAYZONE,-(9 $HRS + $HALFHR)",	# Australian Central Summer
X	  "a.c.s.s.t.",	"$DAYZONE,-(9 $HRS + $HALFHR)",
X	  "awst",	"$ZONE,-8 $HRS",		# Australian Western Time
X	  "a.w.s.t.",	"$ZONE,-8 $HRS"			# (no daylight time there, I'm told)
X	  );
X
X%unittb = (
X	   "year",	"$MUNIT,12",
X	   "month",	"$MUNIT,1",
X	   "fortnight",	"$UNIT,14*24*60",
X	   "week",	"$UNIT,7*24*60",
X	   "day",	"$UNIT,1*24*60",
X	   "hour",	"$UNIT,60",
X	   "minute",	"$UNIT,1",
X	   "min",	"$UNIT,1",
X	   "second",	"$SUNIT,1",
X	   "sec",	"$SUNIT,1"
X	   );
X
X%othertb = (
X	    "tomorrow",	"$UNIT,1*24*60",
X	    "yesterday","$UNIT,-1*24*60",
X	    "today",	"$UNIT,0",
X	    "now",	"$UNIT,0",
X	    "last",	"$NUMBER,-1",
X	    "this",	"$UNIT,0",
X	    "next",	"$NUMBER,2",
X	    "first",	"$NUMBER,1",
X	    # "second",	"$NUMBER,2",
X	    "third",	"$NUMBER,3",
X	    "fourth",	"$NUMBER,4",
X	    "fifth",	"$NUMBER,5",
X	    "sixth",	"$NUMBER,6",
X	    "seventh",	"$NUMBER,7",
X	    "eigth",	"$NUMBER,8",
X	    "ninth",	"$NUMBER,9",
X	    "tenth",	"$NUMBER,10",
X	    "eleventh",	"$NUMBER,11",
X	    "twelfth",	"$NUMBER,12",
X	    "ago",	"$AGO,1"
X	    );
X
X%milzone = (
X	    "a",	"$ZONE,1 $HRS",
X	    "b",	"$ZONE,2 $HRS",
X	    "c",	"$ZONE,3 $HRS",
X	    "d",	"$ZONE,4 $HRS",
X	    "e",	"$ZONE,5 $HRS",
X	    "f",	"$ZONE,6 $HRS",
X	    "g",	"$ZONE,7 $HRS",
X	    "h",	"$ZONE,8 $HRS",
X	    "i",	"$ZONE,9 $HRS",
X	    "k",	"$ZONE,10 $HRS",
X	    "l",	"$ZONE,11 $HRS",
X	    "m",	"$ZONE,12 $HRS",
X	    "n",	"$ZONE,-1 $HRS",
X	    "o",	"$ZONE,-2 $HRS",
X	    "p",	"$ZONE,-3 $HRS",
X	    "q",	"$ZONE,-4 $HRS",
X	    "r",	"$ZONE,-5 $HRS",
X	    "s",	"$ZONE,-6 $HRS",
X	    "t",	"$ZONE,-7 $HRS",
X	    "u",	"$ZONE,-8 $HRS",
X	    "v",	"$ZONE,-9 $HRS",
X	    "w",	"$ZONE,-10 $HRS",
X	    "x",	"$ZONE,-11 $HRS",
X	    "y",	"$ZONE,-12 $HRS",
X	    "z",	"$ZONE,0 $HRS"
X	    );
X
Xsub lookup
X{
X    local($id) = @_;
X    local($abbrev, $idvar, $key, $token);
X
X    $idvar = $id;
X    if (length($idvar) == 3) {
X	$abbrev = 1;
X    }
X    elsif (length($idvar) == 4 && substr($idvar, 3, 1) eq '.') {
X	$abbrev = 1;
X	$idvar = substr($idvar, 0, 3);
X    }
X    else {
X	$abbrev = 0;
X    }
X
X    substr($idvar, 0, 1) =~ tr/a-z/A-Z/;
X    if (defined($mdtab{$idvar})) {
X	($token, $yylval) = split(/,/,$mdtab{$idvar});
X	$yylval = eval "$yylval";
X	return $token;
X    }
X    foreach $key (keys %mdtab) {
X	if ($idvar eq substr($key, 0, 3)) {
X	    ($token, $yylval) = split(/,/,$mdtab{$key});
X	    $yylval = eval "$yylval";
X	    return $token;
X	}
X    }
X    
X    $idvar = $id;
X    if (defined($mztab{$idvar})) {
X	($token, $yylval) = split(/,/,$mztab{$idvar});
X	$yylval = eval "$yylval";
X	return $token;
X    }
X    
X    $idvar =~ tr/A-Z/a-z/;
X    if (defined($mztab{$idvar})) {
X	($token, $yylval) = split(/,/,$mztab{$idvar});
X	$yylval = eval "$yylval";
X	return $token;
X    }
X    
X    $idvar = $id;
X    if (defined($unittab{$idvar})) {
X	($token, $yylval) = split(/,/,$unittab{$idvar});
X	$yylval = eval "$yylval";
X	return $token;
X    }
X    
X    if ($idvar =~ /s$/) {
X	$idvar =~ s/s$//;
X    }
X    if (defined($unittab{$idvar})) {
X	($token, $yylval) = split(/,/,$unittab{$idvar});
X	$yylval = eval "$yylval";
X	return $token;
X    }
X    
X    $idvar = $id;
X    if (defined($othertb{$idvar})) {
X	($token, $yylval) = split(/,/,$othertb{$idvar});
X	$yylval = eval "$yylval";
X	return $token;
X    }
X    
X    if (length($idvar) == 1 && $idvar =~ /a-zA-Z/) {
X	$idvar =~ tr/A-Z/a-z/;
X	if (defined($milzone{$idvar})) {
X	    ($token, $yylval) = split(/,/,$milzone{$idvar});
X	    $yylval = eval "$yylval";
X	    return $token;
X	}
X    }
X    
X    return $ID;
X}
X
Xsub main'getdate
X{
X    local($now, $timezone);
X    local(@lt);
X    local($sdate);
X    local($TZ);
X
X    ($dtstr, $now, $timezone) = @_;
X
X    if (!$now) {
X	$now = time;
X    }
X
X    if (!$timezone) {
X	$TZ = defined($ENV{'TZ'}) ? ($ENV{'TZ'} ? $ENV{'TZ'} : '') : '';
X	if( $TZ =~
X	   /^([^:\d+\-,]{3,})([+-]?\d{1,2}(:\d{1,2}){0,2})([^\d+\-,]{3,})?/) {
X	    $timezone = $2 * 60;
X	}
X	else {
X	    $timezone = 0;
X	}
X    }
X
X    @lt = localtime($now);
X    $year = 0;
X    $month = $lt[4] + 1;
X    $day = $lt[3];
X    $relsec = $relmonth = 0;
X    $timeflag = $zoneflag = $dateflag = $dayflag = $relflag = 0;
X    $daylight = $MAYBE;
X    $hh = $mm = $ss = 0;
X    $merid = 24;
X    
X    return -1 if (&yyparse);
X    
X    return -1 if ($timeflag > 1 || $zoneflag > 1 || $dateflag > 1 || $dayflag > 1);
X
X    if (!$year) {
X	$year = ($month > ($lt[4] + 1)) ? ($lt[5] - 1) : $lt[5];
X    }
X
X    if ($dateflag || $timeflag || $dayflag) {
X	$sdate = &dateconv($month, $day, $year, $hh, $mm, $ss,
X			   $merid, $timezone, $daylight);
X	if ($sdate < 0) {
X	    return -1;
X	}
X    }
X    else {
X	$sdate = $now;
X	if ($relflag == 0) {
X	    $sdate -= ($lt[0] + $lt[1] * 60 + $lt[2] * (60 * 60));
X	}
X    }
X    
X    $sdate += $relsec + &monthadd($sdate, $relmonth);
X    $sdate += &dayconv($dayord, $dayreq, $sdate) if ($dayflag && !$dateflag);
X    
X    return $sdate;
X}
X
Xsub yyerror
X{
X}
X
X1;
END_OF_FILE
  if test 28029 -ne `wc -c <'getdate.pl'`; then
    echo shar: \"'getdate.pl'\" unpacked with wrong size!
  fi
  # end of 'getdate.pl'
fi
if test -f 'getdate.y' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'getdate.y'\"
else
  echo shar: Extracting \"'getdate.y'\" \(14433 characters\)
  sed "s/^X//" >'getdate.y' <<'END_OF_FILE'
X%token ID MONTH DAY MERIDIAN NUMBER UNIT MUNIT SUNIT ZONE DAYZONE AGO
X%{
X# 	Steven M. Bellovin (unc!smb)
X#	Dept. of Computer Science
X#	University of North Carolina at Chapel Hill
X#	@(#)getdate.y	2.13	9/16/86
X#
X#	Richard J. Ohnemus ([email-masked])
X#	(Where do I work??? I'm not even sure who I am! 8-{)
X#	converted to PERL 4/24/92
X
Xpackage getdate;
X
X$daysec = 24 * 60 * 60;
X
X$AM = 1;
X$PM = 2;
X$DAYLIGHT = 1;
X$STANDARD = 2;
X$MAYBE = 3;
X
X%}
X
X%%
Xtimedate: 		/* empty */
X	| timedate item
X	;
X
Xitem:	tspec =
X		{
X		    $timeflag++;
X		}
X	| zone =
X		{
X		    $zoneflag++;
X		}
X	| dtspec =
X		{
X		    $dateflag++;
X		}
X	| dyspec =
X		{
X		    $dayflag++;
X		}
X	| rspec =
X		{
X		    $relflag++;
X		}
X	| nspec
X	;
X
Xnspec:	NUMBER =
X		{
X		    if ($timeflag && $dateflag && !$relflag) {
X			$year = $1;
X		    }
X		    else {
X			$timeflag++;
X			$hh = $1 / 100;
X			$mm = $1 % 100;
X			$ss = 0;
X			$merid = 24;
X		    }
X		}
X	;
X
Xtspec:	NUMBER MERIDIAN =
X		{
X		    $hh = $1;
X		    $mm = 0;
X		    $ss = 0;
X		    $merid = $2;
X		}
X	| NUMBER ':' NUMBER =
X		{
X		    $hh = $1;
X		    $mm = $3;
X		    $merid = 24;
X		}
X	| NUMBER ':' NUMBER MERIDIAN =
X		{
X		    $hh = $1;
X		    $mm = $3;
X		    $merid = $4;
X		}
X	| NUMBER ':' NUMBER NUMBER =
X		{
X		    $hh = $1;
X		    $mm = $3;
X		    $merid = 24;
X		    $daylight = $STANDARD;
X		    $ourzone = $4 % 100 + 60 * $4 / 100;
X		}
X	| NUMBER ':' NUMBER ':' NUMBER =
X		{
X		    $hh = $1;
X		    $mm = $3;
X		    $ss = $5;
X		    $merid = 24;
X		}
X	| NUMBER ':' NUMBER ':' NUMBER MERIDIAN =
X		{
X		    $hh = $1;
X		    $mm = $3;
X		    $ss = $5;
X		    $merid = $6;
X		}
X	| NUMBER ':' NUMBER ':' NUMBER NUMBER =
X		{
X		    $hh = $1;
X		    $mm = $3;
X		    $ss = $5;
X		    $merid = 24;
X		    $daylight = $STANDARD;
X		    $ourzone = $6 % 100 + 60 * $6 / 100;
X		}
X	;
X
Xzone:	ZONE =
X		{
X		    $ourzone = $1;
X		    $daylight = $STANDARD;
X		}
X	| DAYZONE =
X		{
X		    $ourzone = $1;
X		    $daylight = $DAYLIGHT;
X		}
X	;
X
Xdyspec:	DAY =
X		{
X		    $dayord = 1;
X		    $dayreq = $1;
X		}
X	| DAY ',' =
X		{
X		    $dayord = 1;
X		    $dayreq = $1;
X		}
X	| NUMBER DAY =
X		{
X		    $dayord = $1;
X		    $dayreq = $2;
X		}
X	;
X
Xdtspec:	NUMBER '/' NUMBER =
X		{
X		    $month = $1;
X		    $day = $3;
X		}
X	| NUMBER '/' NUMBER '/' NUMBER =
X		{
X		    /*
X		     * HACK ALERT!!!!
X		     * The 1000 is a magic number to attempt to force
X		     * use of 4 digit years if year/month/day can be
X		     * parsed. This was only done for backwards
X		     * compatibility in rh.
X		     */
X		    if ($1 > 1000) {
X			$year = $1;
X			$month = $3;
X			$day = $5;
X		    }
X		    else {
X			$month = $1;
X			$day = $3;
X			$year = $5;
X		    }
X		}
X	| MONTH NUMBER =
X		{
X		    $month = $1;
X		    $day = $2;
X		}
X	| MONTH NUMBER ',' NUMBER =
X		{
X		    $month = $1;
X		    $day = $2;
X		    $year = $4;
X		}
X	| MONTH NUMBER NUMBER ':' NUMBER =
X		{
X		    $month = $1;
X		    $day = $2;
X		    $hh = $3;
X		    $mm = $5;
X		    $merid = 24;
X		    $timeflag++;
X		}
X	| MONTH NUMBER NUMBER =
X		{
X		    $month = $1;
X		    $day = $2;
X		    $year = $3;
X		}
X	| NUMBER MONTH =
X		{
X		    $month = $2;
X		    $day = $1;
X		}
X	| NUMBER MONTH NUMBER =
X		{
X		    $month = $2;
X		    $day = $1;
X		    $year = $3;
X		}
X	;
X
Xrspec:	NUMBER UNIT =
X		{
X		    $relsec +=  60 * $1 * $2;
X		}
X	| NUMBER MUNIT =
X		{
X		    $relmonth += $1 * $2;
X		}
X	| NUMBER SUNIT =
X		{
X		    $relsec += $1;
X		}
X	| UNIT =
X		{
X		    $relsec +=  60 * $1;
X		}
X	| MUNIT =
X		{
X		    $relmonth += $1;
X		}
X	| SUNIT =
X		{
X		    $relsec++;
X		}
X	| rspec AGO =
X		{
X		    $relsec = -$relsec;
X		    $relmonth = -$relmonth;
X		}
X	;
X%%
X
X@mdays = (31, 0, 31,  30, 31, 30,  31, 31, 30,  31, 30, 31);
X$epoch = 1970;
X
Xsub dateconv
X{
X    local($mm, $dd, $yy, $h, $m, $s, $mer, $zone, $dayflag) = @_;
X    local($time_of_day, $jdate);
X    local($i);
X
X    if ($yy < 0) {
X	$yy = -$yy;
X    }
X    if ($yy < 100) {
X	$yy += 1900;
X    }
X    $mdays[1] =
X	28 + (($yy % 4) == 0 && (($yy % 100) != 0 || ($yy % 400) == 0));
X    if ($yy < $epoch || $yy > 2001 || $mm < 1 || $mm > 12
X	|| $dd < 1 || $dd > $mdays[--$mm]) {
X	return -1;
X    }
X    $jdate = $dd - 1;
X    for ($i = 0; $i < $mm; $i++) {
X	$jdate += $mdays[$i];
X    }
X    for ($i = $epoch; $i < $yy; $i++) {
X	$jdate += 365 + (($i % 4) == 0);
X    }
X    $jdate *= $daysec;
X    $jdate += $zone * 60;
X    if (($time_of_day = &timeconv($h, $m, $s, $mer)) < 0) {
X	return -1;
X    }
X    $jdate += $time_of_day;
X    if ($dayflag == $DAYLIGHT
X	|| ($dayflag == $MAYBE && (localtime($jdate))[8])) {
X	$jdate -= 60 * 60;
X    }
X    return $jdate;
X}
X
Xsub dayconv
X{
X    local($ordday, $day, $now) = @_;
X    local(@loctime);
X    local($time_of_day);
X
X    $time_of_day = $now;
X    @loctime = localtime($time_of_day);
X    $time_of_day += $daysec * (($day - $loctime[6] + 7) % 7);
X    $time_of_day += 7 * $daysec * ($ordday <= 0 ? $ordday : $ordday - 1);
X    return &daylcorr($time_of_day, $now);
X}
X
Xsub timeconv
X{
X    local($hh, $mm, $ss, $mer) = @_;
X
X    return -1 if ($mm < 0 || $mm > 59 || $ss < 0 || $ss > 59);
X
X    if ($mer == $AM) {
X	return -1 if ($hh < 1 || $hh > 12);
X	return 60 * (($hh % 12) * 60 + $mm) + $ss;
X    }
X    if ($mer == $PM) {
X	return -1 if ($hh < 1 || $hh > 12);
X	return 60 * (($hh % 12 + 12) * 60 + $mm) + $ss;
X    }
X    if ($mer == 24) {
X	return -1 if ($hh < 0 || $hh > 23);
X	return 60 * ($hh * 60 + $mm) + $ss;
X    }
X    return -1;
X}
X
Xsub monthadd
X{
X    local($sdate, $relmonth) = @_;
X    local(@ltime);
X    local($mm, $yy);
X    
X    return 0 if ($relmonth == 0);
X
X    @ltime = localtime(sdate);
X    $mm = 12 * $ltime[5] + $ltime[4] + $relmonth;
X    $yy = $mm / 12;
X    $mm = $mm % 12 + 1;
X    return &daylcorr(&dateconv($mm, $ltime[3], $yy, $ltime[2],
X			       $ltime[1], $ltime[0], 24, $ourzone, $MAYBE),
X		     $sdate);
X}
X
Xsub daylcorr
X{
X    local($future, $now) = @_;
X    local($fdayl, $nowdayl);		# int
X
X    $nowdayl = ((localtime($now))[2] + 1) % 24;
X    $fdayl = ((localtime($future))[2] + 1) % 24;
X    return ($future - $now) + 60 * 60 * ($nowdayl - $fdayl);
X}
X
Xsub yylex
X{
X    local($pcnt, $sign);
X
X    while (1) {
X	$dtstr =~ s/^\s*//;
X	
X	if ($dtstr =~ /^([-+])/) {
X	    $sign = ($1 eq '-') ? -1 : 1;
X	    $dtstr =~ s/^.//;
X	    if ($dtstr =~ /^(\d+)/) {
X		$yylval = eval "$1 * $sign";
X		$dtstr =~ s/^\d+//;
X		return $NUMBER;
X	    }
X	    else {
X		return &yylex;
X	    }
X	}
X	elsif ($dtstr =~ /^(\d+)/) {
X	    $yylval = eval "$1";
X	    $dtstr =~ s/^\d+//;
X	    return $NUMBER;
X	}
X	elsif ($dtstr =~ /^([a-zA-z][a-zA-Z.]*)/) {
X	    $dtstr = substr($dtstr, length($1));
X	    return &lookup($1);
X	}
X	elsif ($dtstr =~ /^\(/) {
X	    $pcnt = 0;
X	    do {
X		$dtstr = s/^(.)//;
X		return 0 if !defined($1);
X		$pcnt++ if ($1 eq '(');
X		$pcnt-- if ($1 eq ')');
X	    } while ($pcnt > 0);
X	}
X	else {
X	    $yylval = ord(substr($dtstr, 0, 1));
X	    $dtstr =~ s/^.//;
X	    return $yylval;
X	}
X    }
X}
X	
X
X%mdtab = (
X	  "January",	"$MONTH,1",
X	  "February",	"$MONTH,2",
X	  "March", 	"$MONTH,3",
X	  "April",	"$MONTH,4",
X	  "May",	"$MONTH,5",
X	  "June",	"$MONTH,6",
X	  "July",	"$MONTH,7",
X	  "August",	"$MONTH,8",
X	  "September",	"$MONTH,9",
X	  "Sept",	"$MONTH,9",
X	  "October",	"$MONTH,10",
X	  "November",	"$MONTH,11",
X	  "December",	"$MONTH,12",
X
X	  "Sunday",	"$DAY,0",
X	  "Monday",	"$DAY,1",
X	  "Tuesday",	"$DAY,2",
X	  "Tues",	"$DAY,2",
X	  "Wednesday",	"$DAY,3",
X	  "Wednes",	"$DAY,3",
X	  "Thursday",	"$DAY,4",
X	  "Thur",	"$DAY,4",
X	  "Thurs",	"$DAY,4",
X	  "Friday",	"$DAY,5",
X	  "Saturday",	"$DAY,6"
X	  );
X
X$HRS='*60';
X$HALFHR='30';
X
X%mztab = (
X	  "a.m.",	"$MERIDIAN,$AM",
X	  "am",		"$MERIDIAN,$AM",
X	  "p.m.",	"$MERIDIAN,$PM",
X	  "pm",		"$MERIDIAN,$PM",
X	  "nst",	"$ZONE,3 $HRS + $HALFHR",	# Newfoundland
X	  "n.s.t.",	"$ZONE,3 $HRS + $HALFHR",
X	  "ast",	"$ZONE,4 $HRS",			# Atlantic
X	  "a.s.t.",	"$ZONE,4 $HRS",
X	  "adt",	"$DAYZONE,4 $HRS",
X	  "a.d.t.",	"$DAYZONE,4 $HRS",
X	  "est",	"$ZONE,5 $HRS",			# Eastern
X	  "e.s.t.",	"$ZONE,5 $HRS",
X	  "edt",	"$DAYZONE,5 $HRS",
X	  "e.d.t.",	"$DAYZONE,5 $HRS",
X	  "cst",	"$ZONE,6 $HRS",			# Central
X	  "c.s.t.",	"$ZONE,6 $HRS",
X	  "cdt",	"$DAYZONE,6 $HRS",
X	  "c.d.t.",	"$DAYZONE,6 $HRS",
X	  "mst",	"$ZONE,7 $HRS",			# Mountain
X	  "m.s.t.",	"$ZONE,7 $HRS",
X	  "mdt",	"$DAYZONE,7 $HRS",
X	  "m.d.t.",	"$DAYZONE,7 $HRS",
X	  "pst",	"$ZONE,8 $HRS",			# Pacific
X	  "p.s.t.",	"$ZONE,8 $HRS",
X	  "pdt",	"$DAYZONE,8 $HRS",
X	  "p.d.t.",	"$DAYZONE,8 $HRS",
X	  "yst",	"$ZONE,9 $HRS",			# Yukon
X	  "y.s.t.",	"$ZONE,9 $HRS",
X	  "ydt",	"$DAYZONE,9 $HRS",
X	  "y.d.t.",	"$DAYZONE,9 $HRS",
X	  "hst",	"$ZONE,10 $HRS",		# Hawaii
X	  "h.s.t.",	"$ZONE,10 $HRS",
X	  "hdt",	"$DAYZONE,10 $HRS",
X	  "h.d.t.",	"$DAYZONE,10 $HRS",
X
X	  "gmt",	"$ZONE,0 $HRS",
X	  "g.m.t.",	"$ZONE,0 $HRS",
X	  "bst",	"$DAYZONE,0 $HRS",		# British Summer Time
X	  "b.s.t.",	"$DAYZONE,0 $HRS",
X	  "eet",	"$ZONE,0 $HRS",			# European Eastern Time
X	  "e.e.t.",	"$ZONE,0 $HRS",
X	  "eest",	"$DAYZONE,0 $HRS",		# European Eastern Summer Time
X	  "e.e.s.t.",	"$DAYZONE,0 $HRS",
X	  "met",	"$ZONE,-1 $HRS",		# Middle European Time
X	  "m.e.t.",	"$ZONE,-1 $HRS",
X	  "mest",	"$DAYZONE,-1 $HRS",		# Middle European Summer Time
X	  "m.e.s.t.",	"$DAYZONE,-1 $HRS",
X	  "wet",	"$ZONE,-2 $HRS ",		# Western European Time
X	  "w.e.t.",	"$ZONE,-2 $HRS ",
X	  "west",	"$DAYZONE,-2 $HRS",		# Western European Summer Time
X	  "w.e.s.t.",	"$DAYZONE,-2 $HRS",
X
X	  "jst",	"$ZONE,-9 $HRS",		# Japan Standard Time
X	  "j.s.t.",	"$ZONE,-9 $HRS",		# Japan Standard Time
X	  						# No daylight savings time
X
X	  "aest",	"$ZONE,-10 $HRS",		# Australian Eastern Time
X	  "a.e.s.t.",	"$ZONE,-10 $HRS",
X	  "aesst",	"$DAYZONE,-10 $HRS",		# Australian Eastern Summer Time
X	  "a.e.s.s.t.",	"$DAYZONE,-10 $HRS",
X	  "acst",	"$ZONE,-(9 $HRS + $HALFHR)",	# Australian Central Time
X	  "a.c.s.t.",	"$ZONE,-(9 $HRS + $HALFHR)",
X	  "acsst",	"$DAYZONE,-(9 $HRS + $HALFHR)",	# Australian Central Summer
X	  "a.c.s.s.t.",	"$DAYZONE,-(9 $HRS + $HALFHR)",
X	  "awst",	"$ZONE,-8 $HRS",		# Australian Western Time
X	  "a.w.s.t.",	"$ZONE,-8 $HRS"			# (no daylight time there, I'm told)
X	  );
X
X%unittb = (
X	   "year",	"$MUNIT,12",
X	   "month",	"$MUNIT,1",
X	   "fortnight",	"$UNIT,14*24*60",
X	   "week",	"$UNIT,7*24*60",
X	   "day",	"$UNIT,1*24*60",
X	   "hour",	"$UNIT,60",
X	   "minute",	"$UNIT,1",
X	   "min",	"$UNIT,1",
X	   "second",	"$SUNIT,1",
X	   "sec",	"$SUNIT,1"
X	   );
X
X%othertb = (
X	    "tomorrow",	"$UNIT,1*24*60",
X	    "yesterday","$UNIT,-1*24*60",
X	    "today",	"$UNIT,0",
X	    "now",	"$UNIT,0",
X	    "last",	"$NUMBER,-1",
X	    "this",	"$UNIT,0",
X	    "next",	"$NUMBER,2",
X	    "first",	"$NUMBER,1",
X	    # "second",	"$NUMBER,2",
X	    "third",	"$NUMBER,3",
X	    "fourth",	"$NUMBER,4",
X	    "fifth",	"$NUMBER,5",
X	    "sixth",	"$NUMBER,6",
X	    "seventh",	"$NUMBER,7",
X	    "eigth",	"$NUMBER,8",
X	    "ninth",	"$NUMBER,9",
X	    "tenth",	"$NUMBER,10",
X	    "eleventh",	"$NUMBER,11",
X	    "twelfth",	"$NUMBER,12",
X	    "ago",	"$AGO,1"
X	    );
X
X%milzone = (
X	    "a",	"$ZONE,1 $HRS",
X	    "b",	"$ZONE,2 $HRS",
X	    "c",	"$ZONE,3 $HRS",
X	    "d",	"$ZONE,4 $HRS",
X	    "e",	"$ZONE,5 $HRS",
X	    "f",	"$ZONE,6 $HRS",
X	    "g",	"$ZONE,7 $HRS",
X	    "h",	"$ZONE,8 $HRS",
X	    "i",	"$ZONE,9 $HRS",
X	    "k",	"$ZONE,10 $HRS",
X	    "l",	"$ZONE,11 $HRS",
X	    "m",	"$ZONE,12 $HRS",
X	    "n",	"$ZONE,-1 $HRS",
X	    "o",	"$ZONE,-2 $HRS",
X	    "p",	"$ZONE,-3 $HRS",
X	    "q",	"$ZONE,-4 $HRS",
X	    "r",	"$ZONE,-5 $HRS",
X	    "s",	"$ZONE,-6 $HRS",
X	    "t",	"$ZONE,-7 $HRS",
X	    "u",	"$ZONE,-8 $HRS",
X	    "v",	"$ZONE,-9 $HRS",
X	    "w",	"$ZONE,-10 $HRS",
X	    "x",	"$ZONE,-11 $HRS",
X	    "y",	"$ZONE,-12 $HRS",
X	    "z",	"$ZONE,0 $HRS"
X	    );
X
Xsub lookup
X{
X    local($id) = @_;
X    local($abbrev, $idvar, $key, $token);
X
X    $idvar = $id;
X    if (length($idvar) == 3) {
X	$abbrev = 1;
X    }
X    elsif (length($idvar) == 4 && substr($idvar, 3, 1) eq '.') {
X	$abbrev = 1;
X	$idvar = substr($idvar, 0, 3);
X    }
X    else {
X	$abbrev = 0;
X    }
X
X    substr($idvar, 0, 1) =~ tr/a-z/A-Z/;
X    if (defined($mdtab{$idvar})) {
X	($token, $yylval) = split(/,/,$mdtab{$idvar});
X	$yylval = eval "$yylval";
X	return $token;
X    }
X    foreach $key (keys %mdtab) {
X	if ($idvar eq substr($key, 0, 3)) {
X	    ($token, $yylval) = split(/,/,$mdtab{$key});
X	    $yylval = eval "$yylval";
X	    return $token;
X	}
X    }
X    
X    $idvar = $id;
X    if (defined($mztab{$idvar})) {
X	($token, $yylval) = split(/,/,$mztab{$idvar});
X	$yylval = eval "$yylval";
X	return $token;
X    }
X    
X    $idvar =~ tr/A-Z/a-z/;
X    if (defined($mztab{$idvar})) {
X	($token, $yylval) = split(/,/,$mztab{$idvar});
X	$yylval = eval "$yylval";
X	return $token;
X    }
X    
X    $idvar = $id;
X    if (defined($unittab{$idvar})) {
X	($token, $yylval) = split(/,/,$unittab{$idvar});
X	$yylval = eval "$yylval";
X	return $token;
X    }
X    
X    if ($idvar =~ /s$/) {
X	$idvar =~ s/s$//;
X    }
X    if (defined($unittab{$idvar})) {
X	($token, $yylval) = split(/,/,$unittab{$idvar});
X	$yylval = eval "$yylval";
X	return $token;
X    }
X    
X    $idvar = $id;
X    if (defined($othertb{$idvar})) {
X	($token, $yylval) = split(/,/,$othertb{$idvar});
X	$yylval = eval "$yylval";
X	return $token;
X    }
X    
X    if (length($idvar) == 1 && $idvar =~ /a-zA-Z/) {
X	$idvar =~ tr/A-Z/a-z/;
X	if (defined($milzone{$idvar})) {
X	    ($token, $yylval) = split(/,/,$milzone{$idvar});
X	    $yylval = eval "$yylval";
X	    return $token;
X	}
X    }
X    
X    return $ID;
X}
X
Xsub main'getdate
X{
X    local($now, $timezone);
X    local(@lt);
X    local($sdate);
X    local($TZ);
X
X    ($dtstr, $now, $timezone) = @_;
X
X    if (!$now) {
X	$now = time;
X    }
X
X    if (!$timezone) {
X	$TZ = defined($ENV{'TZ'}) ? ($ENV{'TZ'} ? $ENV{'TZ'} : '') : '';
X	if( $TZ =~
X	   /^([^:\d+\-,]{3,})([+-]?\d{1,2}(:\d{1,2}){0,2})([^\d+\-,]{3,})?/) {
X	    $timezone = $2 * 60;
X	}
X	else {
X	    $timezone = 0;
X	}
X    }
X
X    @lt = localtime($now);
X    $year = 0;
X    $month = $lt[4] + 1;
X    $day = $lt[3];
X    $relsec = $relmonth = 0;
X    $timeflag = $zoneflag = $dateflag = $dayflag = $relflag = 0;
X    $daylight = $MAYBE;
X    $hh = $mm = $ss = 0;
X    $merid = 24;
X    
X    return -1 if (&yyparse);
X    
X    return -1 if ($timeflag > 1 || $zoneflag > 1 || $dateflag > 1 || $dayflag > 1);
X
X    if (!$year) {
X	$year = ($month > ($lt[4] + 1)) ? ($lt[5] - 1) : $lt[5];
X    }
X
X    if ($dateflag || $timeflag || $dayflag) {
X	$sdate = &dateconv($month, $day, $year, $hh, $mm, $ss,
X			   $merid, $timezone, $daylight);
X	if ($sdate < 0) {
X	    return -1;
X	}
X    }
X    else {
X	$sdate = $now;
X	if ($relflag == 0) {
X	    $sdate -= ($lt[0] + $lt[1] * 60 + $lt[2] * (60 * 60));
X	}
X    }
X    
X    $sdate += $relsec + &monthadd($sdate, $relmonth);
X    $sdate += &dayconv($dayord, $dayreq, $sdate) if ($dayflag && !$dateflag);
X    
X    return $sdate;
X}
X
Xsub yyerror
X{
X}
X
X1;
END_OF_FILE
  if test 14433 -ne `wc -c <'getdate.y'`; then
    echo shar: \"'getdate.y'\" unpacked with wrong size!
  fi
  # end of 'getdate.y'
fi
echo shar: End of archive 1 \(of 1\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have the archive.
    rm -f ark[1-9]isdone
else
    echo You still must unpack the following archives:
    echo "        " ${MISSING}
fi
exit 0
-- 
Rick Ohnemus   INTERNET: [email-masked]   UUCP: uunet!sparky!rick
LAND: Sterling Software IMD, 1404 Ft. Crook Rd. South, Bellevue NE. 68005-2969
Phone: (402) 291-8300        FAX: (402) 291-4362
I never receive credit for anything I write! (I'm an Ohnemus. 8-)