FYI: date_parse - simple date parsing routine and programs

Monty Solomon monty at roscom.COM
Tue Feb 21 05:54:30 UTC 1995


Newsgroups: alt.sources
From: jef at netcom.com (Jef Poskanzer)
Subject: date_parse - simple date parsing routine and programs
Message-ID: <jefD3uzqC.Mos at netcom.com>
Reply-To: Jef Poskanzer <jef at netcom.com>
Organization: Paratheo-Anametamystikhood Of Eris Esoteric
Date: Sat, 11 Feb 1995 23:25:24 GMT
Lines: 2048
Sender: jef at netcom18.netcom.com

         date_parse - date parsing routine and programs
                     version 1.0 of 11feb95

For a while now I've been somewhat unhappy with the various
date-parsing routines available - yacc-based, lex-based, ad-hoc.  Large
code size and not very portable are the main complaints.  So I wrote a
new one that just does a bunch of sscanf's until one matches.  Slow,
but small and portable.  To figure out what formats to support I did a
survey of Date: lines in a bunch of Usenet articles.  The following two
formats accounted for more than 99% of all articles:

    N mth YYYY HH:MM:SS ampm zone
    wdy, N mth YYYY HH:MM:SS ampm zone

I added Unix ctime() format and a few others:

    wdy mth N HH:MM:SS ampm zone YYYY
    HH:MM:SS ampm zone N mth YYYY
    N mth YYYY
    HH:MM:SS ampm

No-zone, no-seconds, and no-am/pm versions of each are also supported.
Note that dd/mm/yy and mm/dd/yy are NOT supported - those formats are
dumb.

Aside from the date-parsing routine, this package includes some programs
that exercise it:
  o date_sort - sort a file's lines by date
  o date_order - order a list of files by netnews/mail-format Date: lines
  o deltime - subtract two times and show the difference
  o xmit_time - figure transmission time of netnews articles

- - - - - - - - - -

#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	Makefile
#	README
#	ctime.c
#	date_order.1
#	date_order.c
#	date_parse.3
#	date_parse.c
#	date_sort.1
#	date_sort.c
#	deltime.1
#	deltime.c
#	dptest.c
#	test_input
#	test_output
#	xmit_time.1
#	xmit_time.c
# This archive created: Sat Feb 11 15:21:30 1995
# By:	Jef Poskanzer
export PATH; PATH=/bin:$PATH
echo shar: extracting "'Makefile'" '(1873 characters)'
if test -f 'Makefile'
then
	echo shar: will not over-write existing file "'Makefile'"
else
sed 's/^X//' << \SHAR_EOF > 'Makefile'
X# Makefile for date_parse and friends
X
X# CONFIGURE: the directory where you want the library installed
XLIBDIR =	/usr/local/lib
X
X# CONFIGURE: the directory where you want the executables installed
XBINDIR =	/usr/local/bin
X
X# CONFIGURE: the directory tree where you want the man pages installed
XMANDIR =	/usr/local/man
X
X# CONFIGURE: type of system - uncomment one of these
XDEFINES =	-DBSD
X#DEFINES =	-DSYSV
X
X# CONFIGURE: your compiler
X#CC =		cc
XCC =		gcc -ansi -pedantic
X
X# CONFIGURE: your compiler flags
XCFLAGS =	-O $(DEFINES)
X#CFLAGS =	-g $(DEFINES)
X#CFLAGS =	$(DEFINES)
X
X# CONFIGURE: your loader flags
XLDFLAGS =	-s
X#LDFLAGS =	
X
X# End of configurable definitions.
X
XLIB =		libdate_parse.a
XEXES =		date_order date_sort deltime xmit_time
X
Xall:		$(LIB) $(EXES)
X
Xlibdate_parse.a:	date_parse.o
X	rm -f libdate_parse.a
X	ar rc libdate_parse.a date_parse.o
X	-ranlib libdate_parse.a
X
Xdate_order:	date_order.c $(LIB)
X	$(CC) $(CFLAGS) $(LDFLAGS) date_order.c $(LIB) -o date_order
X
Xdate_sort:	date_sort.c $(LIB)
X	$(CC) $(CFLAGS) $(LDFLAGS) date_sort.c $(LIB) -o date_sort
X
Xdeltime:	deltime.c $(LIB)
X	$(CC) $(CFLAGS) $(LDFLAGS) deltime.c $(LIB) -o deltime
X
Xxmit_time:	xmit_time.c $(LIB)
X	$(CC) $(CFLAGS) $(LDFLAGS) xmit_time.c $(LIB) -o xmit_time
X
Xctime:		ctime.c
X	$(CC) $(CFLAGS) $(LDFLAGS) ctime.c -o ctime
X
X.c.o:
X	$(CC) $(CFLAGS) -c $<
X
Xtest:		all dptest
X	./dptest < test_input | diff test_output -
X
Xdptest:		dptest.c $(LIB)
X	$(CC) $(CFLAGS) $(LDFLAGS) dptest.c $(LIB) -o dptest
X
Xinstall:	all
X	for i in $(LIB) ; do \
X	    rm -f $(LIBDIR)/$$i ; \
X	    cp $$i $(LIBDIR) ; \
X	done
X	for i in $(EXES) ; do \
X	    rm -f $(BINDIR)/$$i ; \
X	    cp $$i $(BINDIR) ; \
X	done
X	rm -f $(MANDIR)/man3/date_parse.3
X	cp date_parse.3 $(MANDIR)/man3
X	for i in $(EXES) ; do \
X	    rm -f $(MANDIR)/man1/$$i.1 ; \
X	    cp $$i.1 $(MANDIR)/man1 ; \
X	done
X
Xclean:
X	rm -f *.o *.a $(EXES) dptest ctime a.out core
SHAR_EOF
if test 1873 -ne "`wc -c < 'Makefile'`"
then
	echo shar: error transmitting "'Makefile'" '(should have been 1873  
characters)'
fi
fi # end of overwriting check
echo shar: extracting "'README'" '(1546 characters)'
if test -f 'README'
then
	echo shar: will not over-write existing file "'README'"
else
sed 's/^X//' << \SHAR_EOF > 'README'
X         date_parse - date parsing routine and programs
X                     version 1.0 of 11feb95
X
XFor a while now I've been somewhat unhappy with the various
Xdate-parsing routines available - yacc-based, lex-based, ad-hoc.  Large
Xcode size and not very portable are the main complaints.  So I wrote a
Xnew one that just does a bunch of sscanf's until one matches.  Slow,
Xbut small and portable.  To figure out what formats to support I did a
Xsurvey of Date: lines in a bunch of Usenet articles.  The following two
Xformats accounted for more than 99% of all articles:
X
X    N mth YYYY HH:MM:SS ampm zone
X    wdy, N mth YYYY HH:MM:SS ampm zone
X
XI added Unix ctime() format and a few others:
X
X    wdy mth N HH:MM:SS ampm zone YYYY
X    HH:MM:SS ampm zone N mth YYYY
X    N mth YYYY
X    HH:MM:SS ampm
X
XNo-zone, no-seconds, and no-am/pm versions of each are also supported.
XNote that dd/mm/yy and mm/dd/yy are NOT supported - those formats are
Xdumb.
X
XAside from the date-parsing routine, this package includes some programs
Xthat exercise it:
X  o date_sort - sort a file's lines by date
X  o date_order - order a list of files by netnews/mail-format Date: lines
X  o deltime - subtract two times and show the difference
X  o xmit_time - figure transmission time of netnews articles
X
XSee the manual entries for more details.
X
X
XTo install:
X    Unpack the files.
X    Edit the Makefile to change the configuration options if necessary.
X    Make test to check that it works right.
X    Make install.
X
XComments to:
X    Jef Poskanzer  jef at netcom.com  jef at well.com
SHAR_EOF
if test 1546 -ne "`wc -c < 'README'`"
then
	echo shar: error transmitting "'README'" '(should have been 1546  
characters)'
fi
fi # end of overwriting check
echo shar: extracting "'ctime.c'" '(225 characters)'
if test -f 'ctime.c'
then
	echo shar: will not over-write existing file "'ctime.c'"
else
sed 's/^X//' << \SHAR_EOF > 'ctime.c'
X/* simple debugging tool */
X
X#include <stdio.h>
X#include <time.h>
X
Xvoid
Xmain( argc, argv )
X    int argc;
X    char* argv[];
X    {
X    time_t t;
X
X    t = atoi( argv[1] );
X    printf( "%s\n", ctime( &t ) );
X    exit( 0 );
X    }
SHAR_EOF
if test 225 -ne "`wc -c < 'ctime.c'`"
then
	echo shar: error transmitting "'ctime.c'" '(should have been 225  
characters)'
fi
fi # end of overwriting check
echo shar: extracting "'date_order.1'" '(1535 characters)'
if test -f 'date_order.1'
then
	echo shar: will not over-write existing file "'date_order.1'"
else
sed 's/^X//' << \SHAR_EOF > 'date_order.1'
X.TH date_order 1 "11 February 1995"
X.SH NAME
Xdate_order - order filenames by date
X.SH SYNOPSIS
X.B date_order
X.RI [ file
X.IR ... ]
X.SH DESCRIPTION
X.PP
XGiven a set of filenames as arguments, looks in each file for
Xan email/netnews-format Date: line and writes the filenames out again
Xsorted by the dates.
X.PP
XThis does not change or rearrange the actual files in any way.
XAll it does it produce a new list of the fileNAMEs, sorted by the dates
Xin the files.
X.PP
XThe intended use is with a shell's backquote construct.
XFor instance, if you have a version of uudecode that automatically
Xskips headers and trailers and handles multiple input and output files
X(such as my version),
Xthen you can decode the entire current contents of a picture-newsgroup spool
Xdirectory with one command:
X.nf
X    uudecode `date_order *`
X.fi
XThe reason you want to use date_order instead of just doing "uudecode *"
Xis that netnews articles often arrive out of order.
XUsing date_order hands them to uudecode in the order they were posted.
X.SH "SEE ALSO"
Xdate_sort(1), deltime(1), xmit_time(1), date_parse(3), uudecode(1)
X.SH AUTHOR
XCopyright (C) 1995 by Jef Poskanzer.
X.\" Permission to use, copy, modify, and distribute this software and its
X.\" documentation for any purpose and without fee is hereby granted, provided
X.\" that the above copyright notice appear in all copies and that both that
X.\" copyright notice and this permission notice appear in supporting
X.\" documentation.  This software is provided "as is" without express or
X.\" implied warranty.
SHAR_EOF
if test 1535 -ne "`wc -c < 'date_order.1'`"
then
	echo shar: error transmitting "'date_order.1'" '(should have been 1535  
characters)'
fi
fi # end of overwriting check
echo shar: extracting "'date_order.c'" '(3040 characters)'
if test -f 'date_order.c'
then
	echo shar: will not over-write existing file "'date_order.c'"
else
sed 's/^X//' << \SHAR_EOF > 'date_order.c'
X/* date_order - order filenames by date
X**
X** Copyright (C) 1995 by Jef Poskanzer <jef at netcom.com>.
X**
X** Permission to use, copy, modify, and distribute this software and its
X** documentation for any purpose and without fee is hereby granted, provided
X** that the above copyright notice appear in all copies and that both that
X** copyright notice and this permission notice appear in supporting
X** documentation.  This software is provided "as is" without express or
X** implied warranty.
X*/
X
X#include <stdio.h>
X#include <string.h>
X#include <malloc.h>
X#include <time.h>
X
Xextern time_t date_parse();
X
Xstatic void usage();
Xstatic time_t date_file();
Xstatic int file_compare();
Xstatic char* my_malloc();
Xstatic char* my_realloc();
Xstatic void out_of_mem();
X
Xstatic char* argv0;
X
Xstruct file
X    {
X    char* name;
X    time_t date;
X    };
X
Xstatic int maxfiles, nfiles;
Xstatic struct file* files;
X
Xvoid
Xmain( argc, argv )
X    int argc;
X    char* argv[];
X    {
X    int argn;
X    int i;
X
X    argv0 = argv[0];
X    argn = 1;
X    if ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
X	usage();
X
X    maxfiles = argc - argn;
X    files = (struct file*) my_malloc( maxfiles * sizeof(struct file) );
X    nfiles = 0;
X
X    while ( argn < argc )
X	{
X	files[nfiles].name = (char*) my_malloc( strlen( argv[argn] ) + 1 );
X	(void) strcpy( files[nfiles].name, argv[argn] );
X	files[nfiles].date = date_file( argv[argn] );
X	++nfiles;
X	++argn;
X	}
X
X    qsort( files, nfiles, sizeof(struct file), file_compare );
X
X    for ( i = 0; i < nfiles; ++i )
X	{
X	if ( i != 0 )
X	    putchar( ' ' );
X	fputs( files[i].name, stdout );
X	}
X    putchar( '\n' );
X
X    exit( 0 );
X    }
X
Xstatic void
Xusage()
X    {
X    (void) fprintf( stderr, "usage:  %s [file ...]\n", argv0 );
X    exit( 1 );
X    }
X
Xstatic time_t
Xdate_file( name )
X    char* name;
X    {
X    FILE* f;
X    char line[30000];
X    time_t t;
X
X    f = fopen( name, "r" );
X    if ( f == (FILE*) 0 )
X	{
X	perror( name );
X	return (time_t) -1;
X	}
X
X    for (;;)
X	{
X	if ( fgets( line, sizeof(line), f ) == (char*) 0 )
X	    break;
X	if ( line[0] == '\n' )
X	    break;
X	if ( strncmp( line, "Date:", 5 ) == 0 )
X	    {
X	    (void) fclose( f );
X	    t = date_parse( &line[5] );
X	    if ( t == (time_t) -1 )
X		(void) fprintf(
X		    stderr, "%s: unparsable date in %s - %s",
X		    argv0, name, &line[5] );
X	    return t;
X	    }
X	}
X
X    (void) fprintf( stderr, "%s: no Date: line found in %s\n", argv0, name );
X    (void) fclose( f );
X    return (time_t) -1;
X    }
X
Xstatic int
Xfile_compare( f1, f2 )
X    struct file* f1;
X    struct file* f2;
X    {
X    return f1->date - f2->date;
X    }
X
Xstatic char*
Xmy_malloc( size )
X    unsigned size;
X    {
X    char* r;
X
X    r = malloc( size );
X    if ( r == (char*) 0 )
X	out_of_mem();
X    return r;
X    }
X
Xstatic char*
Xmy_realloc( p, size )
X    char* p;
X    unsigned size;
X    {
X    char* r;
X
X    r = realloc( p, size );
X    if ( r == (char*) 0 )
X	out_of_mem();
X    return r;
X    }
X
Xstatic void
Xout_of_mem()
X    {
X    (void) fprintf( stderr, "%s: out of memory\n", argv0 );
X    exit( 1 );
X    }
SHAR_EOF
if test 3040 -ne "`wc -c < 'date_order.c'`"
then
	echo shar: error transmitting "'date_order.c'" '(should have been 3040  
characters)'
fi
fi # end of overwriting check
echo shar: extracting "'date_parse.3'" '(1789 characters)'
if test -f 'date_parse.3'
then
	echo shar: will not over-write existing file "'date_parse.3'"
else
sed 's/^X//' << \SHAR_EOF > 'date_parse.3'
X.TH date_parse 3 "11 February 1995"
X.SH NAME
Xdate_parse - parse string dates into internal form
X.SH SYNOPSIS
Xtime_t date_parse( char* str )
X.SH DESCRIPTION
X.PP
XParses a date string into standard Unix internal time form (seconds
Xsince epoch).
XThe date should be in one of the following formats:
X.nf
X    N mth YYYY HH:MM:SS ampm zone
X    HH:MM:SS ampm zone N mth YYYY
X    wdy, N mth YYYY HH:MM:SS ampm zone
X    wdy mth N HH:MM:SS ampm zone YYYY
X    N mth YYYY
X    HH:MM:SS ampm
X.fi
XNo-zone, no-seconds, and no-am/pm versions of each are also allowed.
XAny missing parts default to the current date/time.
XNote that dd/mm/yy and mm/dd/yy are not supported - those formats are dumb.
X.SH SPEED
X.PP
XThe implementation is just a bunch of sscanf's - small and portable, but slow.
XStill, it's not that bad.
XOn a SPARCstation 2 parsing ~70000 random dates, the average time
Xwas 0.94 msec/date.
XThis compares surprising well with the lex-based date parser from
Xthe MH package, which took 0.34 msec/date in the same test.
XThe yacc-based parser used in many netnews packages is about halfway
Xbetween the two.
X.PP
XIn any application which has to open a file for each date - and both
XMH and netnews are such applications - the difference in date parsing
Xspeed will not be perceptible to the user.
X.SH "SEE ALSO"
Xdate_sort(1), date_order(1), deltime(1), xmit_time(1)
X.SH AUTHOR
XCopyright (C) 1995 by Jef Poskanzer.
X.\" Permission to use, copy, modify, and distribute this software and its
X.\" documentation for any purpose and without fee is hereby granted, provided
X.\" that the above copyright notice appear in all copies and that both that
X.\" copyright notice and this permission notice appear in supporting
X.\" documentation.  This software is provided "as is" without express or
X.\" implied warranty.
SHAR_EOF
if test 1789 -ne "`wc -c < 'date_parse.3'`"
then
	echo shar: error transmitting "'date_parse.3'" '(should have been 1789  
characters)'
fi
fi # end of overwriting check
echo shar: extracting "'date_parse.c'" '(19522 characters)'
if test -f 'date_parse.c'
then
	echo shar: will not over-write existing file "'date_parse.c'"
else
sed 's/^X//' << \SHAR_EOF > 'date_parse.c'
X/* date_parse - parse string dates into internal form
X**
X** Copyright (C) 1995 by Jef Poskanzer <jef at netcom.com>.
X**
X** Permission to use, copy, modify, and distribute this software and its
X** documentation for any purpose and without fee is hereby granted, provided
X** that the above copyright notice appear in all copies and that both that
X** copyright notice and this permission notice appear in supporting
X** documentation.  This software is provided "as is" without express or
X** implied warranty.
X*/
X
X/* For a while now I've been somewhat unhappy with the various
X** date-parsing routines available - yacc-based, lex-based, ad-hoc.  Large
X** code size and not very portable are the main complaints.  So I wrote a
X** new one that just does a bunch of sscanf's until one matches.  Slow,
X** but small and portable.  To figure out what formats to support I did a
X** survey of Date: lines in a bunch of Usenet articles.  The following
X** two formats accounted for more than 99% of all articles:
X**     N mth YYYY HH:MM:SS ampm zone
X**     wdy, N mth YYYY HH:MM:SS ampm zone
X** I added Unix ctime() format and a few others:
X**     wdy mth N HH:MM:SS ampm zone YYYY
X**     HH:MM:SS ampm zone N mth YYYY
X**     N mth YYYY
X**     HH:MM:SS ampm
X** No-zone, no-seconds, and no-am/pm versions of each are also supported.
X** Note that dd/mm/yy and mm/dd/yy are NOT supported - those formats are
X** dumb.
X*/
X
X#include <sys/types.h>
X#include <stdio.h>
X#include <string.h>
X#include <ctype.h>
X#include <time.h>
X
X#ifdef SYSV
Xextern long timezone;
X#define bzero(p, n) memset(p, 0, n)
X#endif /* SYSV */
X
X#undef DEBUG
X
X#ifdef DEBUG
X#define DP(str) (void) fprintf( stderr, "%s\n", str )
X#else
X#define DP(str) (0)
X#endif
X
Xstruct strint {
X    char* s;
X    int i;
X    };
X
Xstatic void
Xpound_case( str )
X    char* str;
X    {
X    for ( ; *str != '\0'; ++str )
X	{
X	if ( isupper( *str ) )
X	    *str = tolower( *str );
X	}
X    }
X
Xstatic int
Xstrint_compare( v1, v2 )
X    char* v1;
X    char* v2;
X    {
X    return strcmp( ((struct strint*) v1)->s, ((struct strint*) v2)->s );
X    }
X
Xstatic int
Xstrint_search( str, tab, n, iP )
X    char* str;
X    struct strint* tab;
X    int n;
X    int* iP;
X    {
X    int i, h, l, r;
X
X    l = 0;
X    h = n - 1;
X    for (;;)
X	{
X	i = ( h + l ) / 2;
X	r = strcmp( str, tab[i].s );
X	if ( r < 0 )
X	    h = i - 1;
X	else if ( r > 0 )
X	    l = i + 1;
X	else
X	    {
X	    *iP = tab[i].i;
X	    return 1;
X	    }
X	if ( h < l )
X	    return 0;
X	}
X    }
X
X#define AMPM_NONE 0
X#define AMPM_AM 1
X#define AMPM_PM 2
Xstatic int
Xampm_fix( hour, ampm )
X    int hour, ampm;
X    {
X    switch ( ampm )
X	{
X	case AMPM_NONE:
X	break;
X	case AMPM_AM:
X	if ( hour == 12 )
X	    hour = 0;
X	break;
X	case AMPM_PM:
X	if ( hour != 12 )
X	    hour += 12;
X	break;
X	}
X    return hour;
X    }
X
Xstatic int
Xscan_ampm( str_ampm, ampmP )
X    char* str_ampm;
X    int* ampmP;
X    {
X    static struct strint ampm_tab[] = {
X	{ "am", AMPM_AM }, { "pm", AMPM_PM },
X	};
X    static int sorted = 0;
X
X    if ( ! sorted )
X	{
X	(void) qsort(
X	    ampm_tab, sizeof(ampm_tab)/sizeof(struct strint),
X	    sizeof(struct strint), strint_compare );
X	sorted = 1;
X	}
X    pound_case( str_ampm );
X    return strint_search( 

X	str_ampm, ampm_tab, sizeof(ampm_tab)/sizeof(struct strint), ampmP );
X    }
X
Xstatic int
Xscan_wday( str_wday, tm_wdayP )
X    char* str_wday;
X    int* tm_wdayP;
X    {
X    static struct strint wday_tab[] = {
X	{ "sun", 0 }, { "sunday", 0 },
X	{ "mon", 1 }, { "monday", 1 },
X	{ "tue", 2 }, { "tuesday", 2 },
X	{ "wed", 3 }, { "wednesday", 3 },
X	{ "thu", 4 }, { "thursday", 4 },
X	{ "fri", 5 }, { "friday", 5 },
X	{ "sat", 6 }, { "saturday", 6 },
X	};
X    static int sorted = 0;
X
X    if ( ! sorted )
X	{
X	(void) qsort(
X	    wday_tab, sizeof(wday_tab)/sizeof(struct strint),
X	    sizeof(struct strint), strint_compare );
X	sorted = 1;
X	}
X    pound_case( str_wday );
X    return strint_search( 

X	str_wday, wday_tab, sizeof(wday_tab)/sizeof(struct strint), tm_wdayP );
X    }
X
Xstatic int
Xscan_mon( str_mon, tm_monP )
X    char* str_mon;
X    int* tm_monP;
X    {
X    static struct strint mon_tab[] = {
X	{ "jan", 0 }, { "january", 0 },
X	{ "feb", 1 }, { "february", 1 },
X	{ "mar", 2 }, { "march", 2 },
X	{ "apr", 3 }, { "april", 3 },
X	{ "may", 4 },
X	{ "jun", 5 }, { "june", 5 },
X	{ "jul", 6 }, { "july", 6 },
X	{ "aug", 7 }, { "august", 7 },
X	{ "sep", 8 }, { "september", 8 },
X	{ "oct", 9 }, { "october", 9 },
X	{ "nov", 10 }, { "november", 10 },
X	{ "dec", 11 }, { "december", 11 },
X	};
X    static int sorted = 0;
X
X    if ( ! sorted )
X	{
X	(void) qsort(
X	    mon_tab, sizeof(mon_tab)/sizeof(struct strint),
X	    sizeof(struct strint), strint_compare );
X	sorted = 1;
X	}
X    pound_case( str_mon );
X    return strint_search( 

X	str_mon, mon_tab, sizeof(mon_tab)/sizeof(struct strint), tm_monP );
X    }
X
Xstatic int
Xscan_gmtoff( str_gmtoff, gmtoffP )
X    char* str_gmtoff;
X    int* gmtoffP;
X    {
X    static struct strint gmtoff_tab[] = {
X	{ "gmt", 0 }, { "utc", 0 }, { "ut", 0 },
X	{ "0000", 0 }, { "+0000", 0 }, { "-0000", 0 },
X	{ "0100", 3600 }, { "+0100", 3600 }, { "-0100", -3600 },
X	{ "0200", 7200 }, { "+0200", 7200 }, { "-0200", -7200 },
X	{ "0300", 10800 }, { "+0300", 10800 }, { "-0300", -10800 },
X	{ "0400", 14400 }, { "+0400", 14400 }, { "-0400", -14400 },
X	{ "0500", 18000 }, { "+0500", 18000 }, { "-0500", -18000 },
X	{ "0600", 21600 }, { "+0600", 21600 }, { "-0600", -21600 },
X	{ "0700", 25200 }, { "+0700", 25200 }, { "-0700", -25200 },
X	{ "0800", 28800 }, { "+0800", 28800 }, { "-0800", -28800 },
X	{ "0900", 32400 }, { "+0900", 32400 }, { "-0900", -32400 },
X	{ "1000", 36000 }, { "+1000", 36000 }, { "-1000", -36000 },
X	{ "1100", 39600 }, { "+1100", 39600 }, { "-1100", -39600 },
X	{ "1200", 43200 }, { "+1200", 43200 }, { "-1200", -43200 },
X	{ "jst", 7200 }, { "jdt", 10800 },
X	{ "bst", -3600 },
X	{ "nst", -12600 },
X	{ "ast", -14400 }, { "edt", -10800 },
X	{ "est", -18000 }, { "edt", -14400 },
X	{ "cst", -21600 }, { "cdt", -18000 },
X	{ "mst", -25200 }, { "mdt", -21600 },
X	{ "pst", -28800 }, { "pdt", -25200 },
X	{ "yst", -32400 }, { "ydt", -28800 },
X	{ "hst", -36000 }, { "hdt", -32400 },
X	{ "a", -3600 }, { "b", -7200 }, { "c", -10800 }, { "d", -14400 },
X	{ "e", -18000 }, { "f", -21600 }, { "g", -25200 }, { "h", -28800 },
X	{ "i", -32400 }, { "k", -36000 }, { "l", -39600 }, { "m", -43200 },
X	{ "n", -3600 }, { "o", -7200 }, { "p", -10800 }, { "q", -14400 },
X	{ "r", -18000 }, { "s", -21600 }, { "t", -25200 }, { "u", -28800 },
X	{ "v", -32400 }, { "w", -36000 }, { "x", -39600 }, { "y", -43200 },
X	};
X    static int sorted = 0;
X
X    if ( ! sorted )
X	{
X	(void) qsort(
X	    gmtoff_tab, sizeof(gmtoff_tab)/sizeof(struct strint),
X	    sizeof(struct strint), strint_compare );
X	sorted = 1;
X	}
X    pound_case( str_gmtoff );
X    return strint_search( 

X	str_gmtoff, gmtoff_tab, sizeof(gmtoff_tab)/sizeof(struct strint),
X	gmtoffP );
X    }
X
Xstatic int
Xis_leap( year )
X    int year;
X    {
X    return year % 400? ( year % 100 ? ( year % 4 ? 0 : 1 ) : 0 ) : 1;
X    }
X
X/* Basically the same as mktime(). */
Xstatic time_t
Xtm_to_time( tmP )
X    struct tm* tmP;
X    {
X    time_t t;
X    static int monthtab[12] = {
X	0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
X
X    /* Years since epoch, converted to days. */
X    t = ( tmP->tm_year - 70 ) * 365;
X    /* Leap days for previous years. */
X    t += ( tmP->tm_year - 68 ) / 4;
X    /* Days for the beginning of this month. */
X    t += monthtab[tmP->tm_mon];
X    /* Leap day for this year. */
X    if ( tmP->tm_mon >= 2 && is_leap( tmP->tm_year ) )
X	++t;
X    /* Days since the beginning of this month. */
X    t += tmP->tm_mday - 1;	/* 1-based field */
X    /* Hours, minutes, and seconds. */
X    t = t * 24 + tmP->tm_hour;
X    t = t * 60 + tmP->tm_min;
X    t = t * 60 + tmP->tm_sec;
X
X    return t;
X    }
X
Xtime_t
Xdate_parse( str )
X    char* str;
X    {
X    time_t now;
X    struct tm* now_tmP;
X    struct tm tm;
X    char* cp;
X    char str_mon[500], str_wday[500], str_gmtoff[500], str_ampm[500];
X    int tm_sec, tm_min, tm_hour, tm_mday, tm_mon, tm_year, tm_wday, gmtoff;
X    int ampm, got_zone;
X    time_t t;
X
X    /* Initialize tm with relevant parts of current local time. */
X    now = time( (time_t*) 0 );
X    now_tmP = localtime( &now );
X
X    bzero( (char*) &tm, sizeof(struct tm) );
X    tm.tm_sec = now_tmP->tm_sec;
X    tm.tm_min = now_tmP->tm_min;
X    tm.tm_hour = now_tmP->tm_hour;
X    tm.tm_mday = now_tmP->tm_mday;
X    tm.tm_mon = now_tmP->tm_mon;
X    tm.tm_year = now_tmP->tm_year;
X    ampm = AMPM_NONE;
X    got_zone = 0;
X
X    /* Find local zone offset.  This is the only real area of
X    ** non-portability, and it's only used for local times that don't
X    ** specify a zone - those don't occur in email and netnews.
X    */
X#ifdef SYSV
X    tzset();
X    gmtoff = -timezone;
X#else /* SYSV */
X#ifdef BSD
X    gmtoff = now_tmP->tm_gmtoff;
X#else /* BSD */
X    /* You have to fill this in yourself. */
X    gmtoff = !!!;
X#endif /* BSD */
X#endif /* SYSV */
X
X    /* Skip initial whitespace ourselves - sscanf is clumsy at this. */
X    for ( cp = str; *cp == ' ' || *cp == '\t'; ++cp )
X	;
X
X    /* And do the sscanfs.  WARNING: you can add more formats here,
X    ** but be careful!  You can easily screw up the parsing of existing
X    ** formats when you add new ones.
X    */
X
X    /* N mth YYYY HH:MM:SS ampm zone */
X    if ( ( ( sscanf( cp, "%d %[a-zA-Z] %d %d:%d:%d %[apmAPM] %[^: ]",
X		&tm_mday, str_mon, &tm_year, &tm_hour, &tm_min, &tm_sec,
X		str_ampm, str_gmtoff ) == 8 &&
X	    scan_ampm( str_ampm, &ampm ) ) ||
X            sscanf( cp, "%d %[a-zA-Z] %d %d:%d:%d %[^: ]",
X		&tm_mday, str_mon, &tm_year, &tm_hour, &tm_min, &tm_sec,
X		str_gmtoff ) == 7 ) &&
X	    scan_mon( str_mon, &tm_mon ) &&
X	    scan_gmtoff( str_gmtoff, &gmtoff ) )
X	{
X	DP( "N mth YYYY HH:MM:SS ampm zone" );
X	tm.tm_mday = tm_mday;
X	tm.tm_mon = tm_mon;
X	tm.tm_year = tm_year;
X	tm.tm_hour = ampm_fix( tm_hour, ampm );
X	tm.tm_min = tm_min;
X	tm.tm_sec = tm_sec;
X	got_zone = 1;
X	}
X    /* N mth YYYY HH:MM ampm zone */
X    else if ( ( ( sscanf( cp, "%d %[a-zA-Z] %d %d:%d %[apmAPM] %[^: ]",
X		&tm_mday, str_mon, &tm_year, &tm_hour, &tm_min, str_ampm,
X		str_gmtoff ) == 7 &&
X	    scan_ampm( str_ampm, &ampm ) ) ||
X            sscanf( cp, "%d %[a-zA-Z] %d %d:%d %[^: ]",
X		&tm_mday, str_mon, &tm_year, &tm_hour, &tm_min,
X		str_gmtoff ) == 6 ) &&
X	    scan_mon( str_mon, &tm_mon ) &&
X	    scan_gmtoff( str_gmtoff, &gmtoff ) )
X	{
X	DP( "N mth YYYY HH:MM ampm zone" );
X	tm.tm_mday = tm_mday;
X	tm.tm_mon = tm_mon;
X	tm.tm_year = tm_year;
X	tm.tm_hour = ampm_fix( tm_hour, ampm );
X	tm.tm_min = tm_min;
X	tm.tm_sec = 0;
X	got_zone = 1;
X	}
X    /* N mth YYYY HH:MM:SS ampm */
X    else if ( ( ( sscanf( cp, "%d %[a-zA-Z] %d %d:%d:%d %[apmAPM]",
X		&tm_mday, str_mon, &tm_year, &tm_hour, &tm_min, &tm_sec,
X		str_ampm ) == 7 &&
X	    scan_ampm( str_ampm, &ampm ) ) ||
X            sscanf( cp, "%d %[a-zA-Z] %d %d:%d:%d",
X		&tm_mday, str_mon, &tm_year, &tm_hour, &tm_min,
X		&tm_sec ) == 6 ) &&
X	    scan_mon( str_mon, &tm_mon ) )
X	{
X	DP( "N mth YYYY HH:MM:SS ampm" );
X	tm.tm_mday = tm_mday;
X	tm.tm_mon = tm_mon;
X	tm.tm_year = tm_year;
X	tm.tm_hour = ampm_fix( tm_hour, ampm );
X	tm.tm_min = tm_min;
X	tm.tm_sec = tm_sec;
X	}
X    /* N mth YYYY HH:MM ampm */
X    else if ( ( ( sscanf( cp, "%d %[a-zA-Z] %d %d:%d %[apmAPM]",
X		&tm_mday, str_mon, &tm_year, &tm_hour, &tm_min,
X		str_ampm ) == 6 &&
X	    scan_ampm( str_ampm, &ampm ) ) ||
X            sscanf( cp, "%d %[a-zA-Z] %d %d:%d",
X		&tm_mday, str_mon, &tm_year, &tm_hour, &tm_min ) == 5 ) &&
X	    scan_mon( str_mon, &tm_mon ) )
X	{
X	DP( "N mth YYYY HH:MM ampm" );
X	tm.tm_mday = tm_mday;
X	tm.tm_mon = tm_mon;
X	tm.tm_year = tm_year;
X	tm.tm_hour = ampm_fix( tm_hour, ampm );
X	tm.tm_min = tm_min;
X	tm.tm_sec = 0;
X	}
X    /* HH:MM:SS ampm zone N mth YYYY */
X    else if ( ( ( sscanf( cp, "%d:%d:%d %[apmAPM] %[^: ] %d %[a-zA-Z] %d",
X		&tm_hour, &tm_min, &tm_sec, str_ampm, str_gmtoff, &tm_mday,
X		str_mon, &tm_year ) == 8 &&
X	    scan_ampm( str_ampm, &ampm ) ) ||
X	    sscanf( cp, "%d:%d:%d %[^: ] %d %[a-zA-Z] %d",
X		&tm_hour, &tm_min, &tm_sec, str_gmtoff, &tm_mday, str_mon,
X		&tm_year ) == 7 ) &&
X	    scan_gmtoff( str_gmtoff, &gmtoff ) &&
X	    scan_mon( str_mon, &tm_mon ) )
X	{
X	DP( "HH:MM:SS ampm zone N mth YYYY" );
X	tm.tm_hour = ampm_fix( tm_hour, ampm );
X	tm.tm_min = tm_min;
X	tm.tm_sec = tm_sec;
X	tm.tm_mday = tm_mday;
X	tm.tm_mon = tm_mon;
X	tm.tm_year = tm_year;
X	}
X    /* HH:MM ampm zone N mth YYYY */
X    else if ( ( ( sscanf( cp, "%d:%d %[apmAPM] %[^: ] %d %[a-zA-Z] %d",
X		&tm_hour, &tm_min, str_ampm, str_gmtoff, &tm_mday, str_mon,
X		&tm_year ) == 7 &&
X	    scan_ampm( str_ampm, &ampm ) ) ||
X	    sscanf( cp, "%d:%d %[^: ] %d %[a-zA-Z] %d",
X		&tm_hour, &tm_min, str_gmtoff, &tm_mday, str_mon,
X		&tm_year ) == 6 ) &&
X	    scan_gmtoff( str_gmtoff, &gmtoff ) &&
X	    scan_mon( str_mon, &tm_mon ) )
X	{
X	DP( "HH:MM ampm N mth YYYY" );
X	tm.tm_hour = ampm_fix( tm_hour, ampm );
X	tm.tm_min = tm_min;
X	tm.tm_sec = 0;
X	tm.tm_mday = tm_mday;
X	tm.tm_mon = tm_mon;
X	tm.tm_year = tm_year;
X	}
X    /* HH:MM:SS ampm N mth YYYY */
X    else if ( ( ( sscanf( cp, "%d:%d:%d %[apmAPM] %d %[a-zA-Z] %d",
X		&tm_hour, &tm_min, &tm_sec, str_ampm, &tm_mday, str_mon,
X		&tm_year ) == 7 &&
X	    scan_ampm( str_ampm, &ampm ) ) ||
X	    sscanf( cp, "%d:%d:%d %d %[a-zA-Z] %d",
X		&tm_hour, &tm_min, &tm_sec, &tm_mday, str_mon,
X		&tm_year ) == 6 ) &&
X	    scan_mon( str_mon, &tm_mon ) )
X	{
X	DP( "HH:MM:SS ampm N mth YYYY" );
X	tm.tm_hour = ampm_fix( tm_hour, ampm );
X	tm.tm_min = tm_min;
X	tm.tm_sec = tm_sec;
X	tm.tm_mday = tm_mday;
X	tm.tm_mon = tm_mon;
X	tm.tm_year = tm_year;
X	}
X    /* HH:MM ampm N mth YYYY */
X    else if ( ( ( sscanf( cp, "%d:%d %[apmAPM] %d %[a-zA-Z] %d",
X		&tm_hour, &tm_min, str_ampm, &tm_mday, str_mon,
X		&tm_year ) == 6 &&
X	    scan_ampm( str_ampm, &ampm ) ) ||
X	    sscanf( cp, "%d:%d %d %[a-zA-Z] %d",
X		&tm_hour, &tm_min, &tm_mday, str_mon, &tm_year ) == 5 ) &&
X	    scan_mon( str_mon, &tm_mon ) )
X	{
X	DP( "HH:MM ampm N mth YYYY" );
X	tm.tm_hour = ampm_fix( tm_hour, ampm );
X	tm.tm_min = tm_min;
X	tm.tm_sec = 0;
X	tm.tm_mday = tm_mday;
X	tm.tm_mon = tm_mon;
X	tm.tm_year = tm_year;
X	}
X    /* wdy, N mth YYYY HH:MM:SS ampm zone */
X    else if ( ( ( sscanf( cp, "%[a-zA-Z], %d %[a-zA-Z] %d %d:%d:%d %[apmAPM] %[^:  
]",
X		str_wday, &tm_mday, str_mon, &tm_year, &tm_hour, &tm_min,
X		&tm_sec, str_ampm, str_gmtoff ) == 9 &&
X	    scan_ampm( str_ampm, &ampm ) ) ||
X	    sscanf( cp, "%[a-zA-Z], %d %[a-zA-Z] %d %d:%d:%d %[^: ]",
X		str_wday, &tm_mday, str_mon, &tm_year, &tm_hour, &tm_min,
X		&tm_sec, str_gmtoff ) == 8 ) &&
X	    scan_wday( str_wday, &tm_wday ) &&
X	    scan_mon( str_mon, &tm_mon ) &&
X	    scan_gmtoff( str_gmtoff, &gmtoff ) )
X	{
X	DP( "wdy, N mth YYYY HH:MM:SS ampm zone" );
X	tm.tm_wday = tm_wday;
X	tm.tm_mday = tm_mday;
X	tm.tm_mon = tm_mon;
X	tm.tm_year = tm_year;
X	tm.tm_hour = ampm_fix( tm_hour, ampm );
X	tm.tm_min = tm_min;
X	tm.tm_sec = tm_sec;
X	got_zone = 1;
X	}
X    /* wdy, N mth YYYY HH:MM ampm zone */
X    else if ( ( ( sscanf( cp, "%[a-zA-Z], %d %[a-zA-Z] %d %d:%d %[apmAPM] %[^: ]",
X		str_wday, &tm_mday, str_mon, &tm_year, &tm_hour, &tm_min,
X		str_ampm, str_gmtoff ) == 8 &&
X	    scan_ampm( str_ampm, &ampm ) ) ||
X	    sscanf( cp, "%[a-zA-Z], %d %[a-zA-Z] %d %d:%d %[^: ]",
X		str_wday, &tm_mday, str_mon, &tm_year, &tm_hour, &tm_min,
X		str_gmtoff ) == 7 ) &&
X	    scan_wday( str_wday, &tm_wday ) &&
X	    scan_mon( str_mon, &tm_mon ) &&
X	    scan_gmtoff( str_gmtoff, &gmtoff ) )
X	{
X	DP( "wdy, N mth YYYY HH:MM ampm zone" );
X	tm.tm_wday = tm_wday;
X	tm.tm_mday = tm_mday;
X	tm.tm_mon = tm_mon;
X	tm.tm_year = tm_year;
X	tm.tm_hour = ampm_fix( tm_hour, ampm );
X	tm.tm_min = tm_min;
X	tm.tm_sec = 0;
X	got_zone = 1;
X	}
X    /* wdy, N mth YYYY HH:MM:SS ampm */
X    else if ( ( ( sscanf( cp, "%[a-zA-Z], %d %[a-zA-Z] %d %d:%d:%d %[apmAPM]",
X		str_wday, &tm_mday, str_mon, &tm_year, &tm_hour, &tm_min,
X		&tm_sec, str_ampm ) == 8 &&
X	    scan_ampm( str_ampm, &ampm ) ) ||
X	    sscanf( cp, "%[a-zA-Z], %d %[a-zA-Z] %d %d:%d:%d",
X		str_wday, &tm_mday, str_mon, &tm_year, &tm_hour, &tm_min,
X		&tm_sec ) == 7 ) &&
X	    scan_wday( str_wday, &tm_wday ) &&
X	    scan_mon( str_mon, &tm_mon ) )
X	{
X	DP( "wdy, N mth YYYY HH:MM:SS ampm" );
X	tm.tm_wday = tm_wday;
X	tm.tm_mday = tm_mday;
X	tm.tm_mon = tm_mon;
X	tm.tm_year = tm_year;
X	tm.tm_hour = ampm_fix( tm_hour, ampm );
X	tm.tm_min = tm_min;
X	tm.tm_sec = tm_sec;
X	}
X    /* wdy, N mth YYYY HH:MM ampm */
X    else if ( ( ( sscanf( cp, "%[a-zA-Z], %d %[a-zA-Z] %d %d:%d %[apmAPM]",
X		str_wday, &tm_mday, str_mon, &tm_year, &tm_hour, &tm_min,
X		str_ampm ) == 7 &&
X	    scan_ampm( str_ampm, &ampm ) ) ||
X	    sscanf( cp, "%[a-zA-Z], %d %[a-zA-Z] %d %d:%d",
X		str_wday, &tm_mday, str_mon, &tm_year, &tm_hour,
X		&tm_min ) == 6 ) &&
X	    scan_wday( str_wday, &tm_wday ) &&
X	    scan_mon( str_mon, &tm_mon ) )
X	{
X	DP( "wdy, N mth YYYY HH:MM ampm" );
X	tm.tm_wday = tm_wday;
X	tm.tm_mday = tm_mday;
X	tm.tm_mon = tm_mon;
X	tm.tm_year = tm_year;
X	tm.tm_hour = ampm_fix( tm_hour, ampm );
X	tm.tm_min = tm_min;
X	tm.tm_sec = 0;
X	}
X    /* wdy mth N HH:MM:SS ampm zone YYYY */
X    else if ( ( ( sscanf( cp, "%[a-zA-Z] %[a-zA-Z] %d %d:%d:%d %[apmAPM] %[^: ]  
%d",
X		str_wday, str_mon, &tm_mday, &tm_hour, &tm_min, &tm_sec,
X		str_ampm, str_gmtoff, &tm_year ) == 9 &&
X	    scan_ampm( str_ampm, &ampm ) ) ||
X	    sscanf( cp, "%[a-zA-Z] %[a-zA-Z] %d %d:%d:%d %[^: ] %d",
X		str_wday, str_mon, &tm_mday, &tm_hour, &tm_min, &tm_sec,
X		str_gmtoff, &tm_year ) == 8 ) &&
X	    scan_wday( str_wday, &tm_wday ) &&
X	    scan_mon( str_mon, &tm_mon ) &&
X	    scan_gmtoff( str_gmtoff, &gmtoff ) )
X	{
X	DP( "wdy mth N HH:MM:SS ampm zone YYYY" );
X	tm.tm_wday = tm_wday;
X	tm.tm_mon = tm_mon;
X	tm.tm_mday = tm_mday;
X	tm.tm_hour = ampm_fix( tm_hour, ampm );
X	tm.tm_min = tm_min;
X	tm.tm_sec = tm_sec;
X	got_zone = 1;
X	tm.tm_year = tm_year;
X	}
X    /* wdy mth N HH:MM ampm zone YYYY */
X    else if ( ( ( sscanf( cp, "%[a-zA-Z] %[a-zA-Z] %d %d:%d %[apmAPM] %[^: ] %d",
X	    str_wday, str_mon, &tm_mday, &tm_hour, &tm_min,
X	    str_ampm, str_gmtoff, &tm_year ) == 8 &&
X	    scan_ampm( str_ampm, &ampm ) ) ||
X	    sscanf( cp, "%[a-zA-Z] %[a-zA-Z] %d %d:%d %[^: ] %d",
X		str_wday, str_mon, &tm_mday, &tm_hour, &tm_min,
X		str_gmtoff, &tm_year ) == 7 ) &&
X	    scan_wday( str_wday, &tm_wday ) &&
X	    scan_mon( str_mon, &tm_mon ) &&
X	    scan_gmtoff( str_gmtoff, &gmtoff ) )
X	{
X	DP( "wdy mth N HH:MM ampm zone YYYY" );
X	tm.tm_wday = tm_wday;
X	tm.tm_mon = tm_mon;
X	tm.tm_mday = tm_mday;
X	tm.tm_hour = ampm_fix( tm_hour, ampm );
X	tm.tm_min = tm_min;
X	tm.tm_sec = 0;
X	got_zone = 1;
X	tm.tm_year = tm_year;
X	}
X    /* N mth YYYY */
X    else if ( sscanf( cp, "%d %[a-zA-Z] %d",
X	    &tm_mday, str_mon, &tm_year ) == 3 &&
X	    scan_mon( str_mon, &tm_mon ) )
X	{
X	DP( "N mth YYYY" );
X	tm.tm_mday = tm_mday;
X	tm.tm_mon = tm_mon;
X	tm.tm_year = tm_year;
X	tm.tm_hour = 0;
X	tm.tm_min = 0;
X	tm.tm_sec = 0;
X	}
X    /* HH:MM:SS ampm */
X    else if ( ( sscanf( cp, "%d:%d:%d %[apmAPM]",
X	    &tm_hour, &tm_min, &tm_sec, str_ampm ) == 4 &&
X	    scan_ampm( str_ampm, &ampm ) ) ||
X	    sscanf( cp, "%d:%d:%d", &tm_hour, &tm_min, &tm_sec ) == 3 )
X	{
X	DP( "HH:MM:SS ampm" );
X	tm.tm_hour = ampm_fix( tm_hour, ampm );
X	tm.tm_min = tm_min;
X	tm.tm_sec = tm_sec;
X	}
X    /* HH:MM ampm */
X    else if ( ( sscanf( cp, "%d:%d %[apmAPM]", &tm_hour, &tm_min,
X		str_ampm ) == 3 &&
X	    scan_ampm( str_ampm, &ampm ) ) ||
X	    sscanf( cp, "%d:%d", &tm_hour, &tm_min ) == 2 )
X	{
X	DP( "HH:MM" );
X	tm.tm_hour = ampm_fix( tm_hour, ampm );
X	tm.tm_min = tm_min;
X	tm.tm_sec = 0;
X	}
X    else
X	return (time_t) -1;
X
X    if ( tm.tm_year > 1900 )
X	tm.tm_year -= 1900;
X    else if ( tm.tm_year < 70 )
X	tm.tm_year += 100;
X
X    t = tm_to_time( &tm );
X    t -= gmtoff;
X    if ( tm.tm_isdst && ! got_zone )
X	t -= 60*60;
X
X    return t;
X    }
SHAR_EOF
if test 19522 -ne "`wc -c < 'date_parse.c'`"
then
	echo shar: error transmitting "'date_parse.c'" '(should have been 19522  
characters)'
fi
fi # end of overwriting check
echo shar: extracting "'date_sort.1'" '(784 characters)'
if test -f 'date_sort.1'
then
	echo shar: will not over-write existing file "'date_sort.1'"
else
sed 's/^X//' << \SHAR_EOF > 'date_sort.1'
X.TH date_sort 1 "11 February 1995"
X.SH NAME
Xdate_sort - sort input by date
X.SH SYNOPSIS
X.B date_sort
X.RI [ file
X.IR ... ]
X.SH DESCRIPTION
X.PP
XReads in lines from the input files or stdin.
XThe lines should consist of or begin with dates.
XSorts the lines and writes them out.
X.SH "SEE ALSO"
Xdate_order(1), deltime(1), xmit_time(1), date_parse(3)
X.SH AUTHOR
XCopyright (C) 1995 by Jef Poskanzer.
X.\" Permission to use, copy, modify, and distribute this software and its
X.\" documentation for any purpose and without fee is hereby granted, provided
X.\" that the above copyright notice appear in all copies and that both that
X.\" copyright notice and this permission notice appear in supporting
X.\" documentation.  This software is provided "as is" without express or
X.\" implied warranty.
SHAR_EOF
if test 784 -ne "`wc -c < 'date_sort.1'`"
then
	echo shar: error transmitting "'date_sort.1'" '(should have been 784  
characters)'
fi
fi # end of overwriting check
echo shar: extracting "'date_sort.c'" '(3085 characters)'
if test -f 'date_sort.c'
then
	echo shar: will not over-write existing file "'date_sort.c'"
else
sed 's/^X//' << \SHAR_EOF > 'date_sort.c'
X/* date_sort - sort input by date
X**
X** Copyright (C) 1995 by Jef Poskanzer <jef at netcom.com>.
X**
X** Permission to use, copy, modify, and distribute this software and its
X** documentation for any purpose and without fee is hereby granted, provided
X** that the above copyright notice appear in all copies and that both that
X** copyright notice and this permission notice appear in supporting
X** documentation.  This software is provided "as is" without express or
X** implied warranty.
X*/
X
X#include <stdio.h>
X#include <string.h>
X#include <malloc.h>
X#include <time.h>
X
Xextern time_t date_parse();
X
Xstatic void usage();
Xstatic void read_file();
Xstatic int line_compare();
Xstatic char* my_malloc();
Xstatic char* my_realloc();
Xstatic void out_of_mem();
X
Xstatic char* argv0;
X
Xstruct line
X    {
X    char* text;
X    time_t date;
X    };
X
Xstatic int maxlines, nlines;
Xstatic struct line* lines;
X
Xvoid
Xmain( argc, argv )
X    int argc;
X    char* argv[];
X    {
X    int argn;
X    FILE* f;
X    int i;
X
X    argv0 = argv[0];
X    argn = 1;
X    if ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
X	usage();
X
X    maxlines = 500;		/* arbitrary initial value */
X    lines = (struct line*) my_malloc( maxlines * sizeof(struct line) );
X    nlines = 0;
X
X    if ( argn == argc )
X	read_file( stdin );
X    else
X	while ( argn < argc )
X	    {
X	    if ( strcmp( argv[argn], "-" ) == 0 )
X		read_file( stdin );
X	    else
X		{
X		f = fopen( argv[argn], "r" );
X		if ( f == (FILE*) 0 )
X		    {
X		    perror( argv[argn] );
X		    exit( 1 );
X		    }
X		read_file( f );
X		(void) fclose( f );
X		}
X	    ++argn;
X	    }
X
X    qsort( lines, nlines, sizeof(struct line), line_compare );
X
X    for ( i = 0; i < nlines; ++i )
X	fputs( lines[i].text, stdout );
X
X    exit( 0 );
X    }
X
Xstatic void
Xusage()
X    {
X    (void) fprintf( stderr, "usage:  %s [file ...]\n", argv0 );
X    exit( 1 );
X    }
X
Xstatic void
Xread_file( f )
X    FILE* f;
X    {
X    char aline[10000];
X
X    /* Read until end of file. */
X    while ( fgets( aline, sizeof(aline), f ) != (char*) 0 )
X	{
X	/* Make sure there's enough room in the lines array. */
X	if ( nlines >= maxlines )
X	    {
X	    maxlines *= 2;
X	    lines = (struct line*) my_realloc(
X		(char*) lines, maxlines * sizeof(struct line) );
X	    }
X	lines[nlines].text = (char*) my_malloc( strlen( aline ) + 1 );
X	(void) strcpy( lines[nlines].text, aline );
X	lines[nlines].date = date_parse( aline );
X	if ( lines[nlines].date == (time_t) -1 )
X	    (void) fprintf( stderr, "%s: unparsable date - %s", argv0, aline );
X	++nlines;
X	}
X    }
X
Xstatic int
Xline_compare( l1, l2 )
X    struct line* l1;
X    struct line* l2;
X    {
X    return l1->date - l2->date;
X    }
X
Xstatic char*
Xmy_malloc( size )
X    unsigned size;
X    {
X    char* r;
X
X    r = malloc( size );
X    if ( r == (char*) 0 )
X	out_of_mem();
X    return r;
X    }
X
Xstatic char*
Xmy_realloc( p, size )
X    char* p;
X    unsigned size;
X    {
X    char* r;
X
X    r = realloc( p, size );
X    if ( r == (char*) 0 )
X	out_of_mem();
X    return r;
X    }
X
Xstatic void
Xout_of_mem()
X    {
X    (void) fprintf( stderr, "%s: out of memory\n", argv0 );
X    exit( 1 );
X    }
SHAR_EOF
if test 3085 -ne "`wc -c < 'date_sort.c'`"
then
	echo shar: error transmitting "'date_sort.c'" '(should have been 3085  
characters)'
fi
fi # end of overwriting check
echo shar: extracting "'deltime.1'" '(978 characters)'
if test -f 'deltime.1'
then
	echo shar: will not over-write existing file "'deltime.1'"
else
sed 's/^X//' << \SHAR_EOF > 'deltime.1'
X.TH deltime 1 "11 February 1995"
X.SH NAME
Xdeltime - show difference between two dates
X.SH SYNOPSIS
X.B deltime
X.I date1
X.RI [ date2 ]
X.SH DESCRIPTION
X.PP
XComputes the elapsed time between now and a
Xspecified date/time, or between two specified date/times.
XBe careful to put the dates in quotes if they contain spaces.
XThe output format is dddd hh:mm:ss.
X.PP
XTimes earlier than 1970 cannot
Xbe handled, because that's as far back as the internal Unix time format goes.
X.SH "SEE ALSO"
Xdate_sort(1), date_order(1), xmit_time(1), date_parse(3)
X.SH AUTHOR
XCopyright (C) 1995 by Jef Poskanzer.
X.\" Permission to use, copy, modify, and distribute this software and its
X.\" documentation for any purpose and without fee is hereby granted, provided
X.\" that the above copyright notice appear in all copies and that both that
X.\" copyright notice and this permission notice appear in supporting
X.\" documentation.  This software is provided "as is" without express or
X.\" implied warranty.
SHAR_EOF
if test 978 -ne "`wc -c < 'deltime.1'`"
then
	echo shar: error transmitting "'deltime.1'" '(should have been 978  
characters)'
fi
fi # end of overwriting check
echo shar: extracting "'deltime.c'" '(1932 characters)'
if test -f 'deltime.c'
then
	echo shar: will not over-write existing file "'deltime.c'"
else
sed 's/^X//' << \SHAR_EOF > 'deltime.c'
X/* deltime - show difference between two dates
X**
X** Copyright (C) 1995 by Jef Poskanzer <jef at netcom.com>.
X**
X** Permission to use, copy, modify, and distribute this software and its
X** documentation for any purpose and without fee is hereby granted, provided
X** that the above copyright notice appear in all copies and that both that
X** copyright notice and this permission notice appear in supporting
X** documentation.  This software is provided "as is" without express or
X** implied warranty.
X*/
X
X#include <stdio.h>
X#include <time.h>
X
Xextern time_t date_parse();
X
Xstatic void usage();
Xstatic void unparsable();
X
Xstatic char* argv0;
X
X#define SECSPERMINUTE 60
X#define SECSPERHOUR (60 * SECSPERMINUTE)
X#define SECSPERDAY (24 * SECSPERHOUR)
X
Xvoid
Xmain( argc, argv )
X    int argc;
X    char* argv[];
X    {
X    time_t t1, t2;
X    long delta;
X    int days, hours, minutes, secs;
X
X    argv0 = argv[0];
X
X    if ( argc == 2 )
X	{
X	t1 = date_parse( argv[1] );
X	if ( t1 == (time_t) -1 )
X	    unparsable( argv[1] );
X	t2 = time( (time_t*) 0 );
X	}
X    else if ( argc == 3 )
X	{
X	t1 = date_parse( argv[1] );
X	if ( t1 == (time_t) -1 )
X	    unparsable( argv[1] );
X	t2 = date_parse( argv[2] );
X	if ( t2 == (time_t) -1 )
X	    unparsable( argv[2] );
X	}
X    else
X	usage();
X
X    delta = t2 - t1;
X    if ( delta < 0 )
X	{
X	(void) printf( "-" );
X	delta = -delta;
X	}
X
X    days = delta / SECSPERDAY;
X    delta = delta - days * SECSPERDAY;
X    hours = delta / SECSPERHOUR;
X    delta = delta - hours * SECSPERHOUR;
X    minutes = delta / SECSPERMINUTE;
X    delta = delta - minutes * SECSPERMINUTE;
X    secs = delta;
X
X    printf( "%d %2d:%02d:%02d\n", days, hours, minutes, secs );
X
X    exit( 0 );
X    }
X
Xstatic void
Xusage()
X    {
X    (void) fprintf( stderr, "usage:  %s date1 [date2]\n", argv0 );
X    exit( 1 );
X    }
X
Xstatic void
Xunparsable( str )
X    char* str;
X    {
X    (void) fprintf( stderr, "%s: unparsable date - %s\n", argv0, str );
X    exit( 1 );
X    }
SHAR_EOF
if test 1932 -ne "`wc -c < 'deltime.c'`"
then
	echo shar: error transmitting "'deltime.c'" '(should have been 1932  
characters)'
fi
fi # end of overwriting check
echo shar: extracting "'dptest.c'" '(286 characters)'
if test -f 'dptest.c'
then
	echo shar: will not over-write existing file "'dptest.c'"
else
sed 's/^X//' << \SHAR_EOF > 'dptest.c'
X#include <sys/types.h>
X#include <stdio.h>
X#include <time.h>
X
Xextern time_t date_parse();
X
Xmain( argc, argv )
X    int argc;
X    char* argv;
X    {
X    char line[5000];
X
X    while ( gets( line ) != (char*) 0 )
X	(void) printf( "%s - %d\n", line, date_parse( line ) );
X
X    exit( 0 );
X    }
SHAR_EOF
if test 286 -ne "`wc -c < 'dptest.c'`"
then
	echo shar: error transmitting "'dptest.c'" '(should have been 286  
characters)'
fi
fi # end of overwriting check
echo shar: extracting "'test_input'" '(4336 characters)'
if test -f 'test_input'
then
	echo shar: will not over-write existing file "'test_input'"
else
sed 's/^X//' << \SHAR_EOF > 'test_input'
X6 Feb 1995 09:00:00 AM PST
X6 Feb 1995 09:00:00 PST
X6 Feb 1995 09:00 AM PST
X6 Feb 1995 09:00 PST
X6 Feb 1995 09:00:00 AM
X6 Feb 1995 09:00:00
X6 Feb 1995 09:00 AM
X6 Feb 1995 09:00
X09:00:00 AM PST 6 Feb 1995
X09:00:00 PST 6 Feb 1995
X09:00 AM PST 6 Feb 1995
X09:00 PST 6 Feb 1995
X09:00:00 AM 6 Feb 1995
X09:00:00 6 Feb 1995
X09:00 AM 6 Feb 1995
X09:00 6 Feb 1995
XMon, 6 Feb 1995 09:00:00 AM PST
XMon, 6 Feb 1995 09:00:00 PST
XMon, 6 Feb 1995 09:00 AM PST
XMon, 6 Feb 1995 09:00 PST
XMon, 6 Feb 1995 09:00:00 AM
XMon, 6 Feb 1995 09:00:00
XMon, 6 Feb 1995 09:00 AM
XMon, 6 Feb 1995 09:00
XMon Feb 6 09:00:00 AM PST 1995
XMon Feb 6 09:00:00 PST 1995
XMon Feb 6 09:00 AM PST 1995
XMon Feb 6 09:00 PST 1995
XMon, 6 Feb 1995 09:00:00 AM PST
XMon, 6 Feb 1995 09:00:00 PM PST
XSun, 6 Feb 1995 09:00:00 PST
XSunday, 6 Feb 1995 09:00:00 PST
XMon, 6 Feb 1995 09:00:00 PST
XMonday, 6 Feb 1995 09:00:00 PST
XTue, 6 Feb 1995 09:00:00 PST
XTuesday, 6 Feb 1995 09:00:00 PST
XWed, 6 Feb 1995 09:00:00 PST
XWednesday, 6 Feb 1995 09:00:00 PST
XThu, 6 Feb 1995 09:00:00 PST
XThursday, 6 Feb 1995 09:00:00 PST
XFri, 6 Feb 1995 09:00:00 PST
XFriday, 6 Feb 1995 09:00:00 PST
XSat, 6 Feb 1995 09:00:00 PST
XSaturday, 6 Feb 1995 09:00:00 PST
XMon, 6 Jan 1995 09:00:00 PST
XMon, 6 January 1995 09:00:00 PST
XMon, 6 Feb 1995 09:00:00 PST
XMon, 6 February 1995 09:00:00 PST
XMon, 6 Mar 1995 09:00:00 PST
XMon, 6 March 1995 09:00:00 PST
XMon, 6 Apr 1995 09:00:00 PST
XMon, 6 April 1995 09:00:00 PST
XMon, 6 May 1995 09:00:00 PST
XMon, 6 Jun 1995 09:00:00 PST
XMon, 6 June 1995 09:00:00 PST
XMon, 6 Jul 1995 09:00:00 PST
XMon, 6 July 1995 09:00:00 PST
XMon, 6 Aug 1995 09:00:00 PST
XMon, 6 August 1995 09:00:00 PST
XMon, 6 Sep 1995 09:00:00 PST
XMon, 6 September 1995 09:00:00 PST
XMon, 6 Oct 1995 09:00:00 PST
XMon, 6 October 1995 09:00:00 PST
XMon, 6 Nov 1995 09:00:00 PST
XMon, 6 November 1995 09:00:00 PST
XMon, 6 Dec 1995 09:00:00 PST
XMon, 6 December 1995 09:00:00 PST
XMon, 6 Feb 1995 09:00:00 GMT
XMon, 6 Feb 1995 09:00:00 UTC
XMon, 6 Feb 1995 09:00:00 UT
XMon, 6 Feb 1995 09:00:00 0000
XMon, 6 Feb 1995 09:00:00 +0000
XMon, 6 Feb 1995 09:00:00 -0000
XMon, 6 Feb 1995 09:00:00 0100
XMon, 6 Feb 1995 09:00:00 +0100
XMon, 6 Feb 1995 09:00:00 -0100
XMon, 6 Feb 1995 09:00:00 0200
XMon, 6 Feb 1995 09:00:00 +0200
XMon, 6 Feb 1995 09:00:00 -0200
XMon, 6 Feb 1995 09:00:00 0300
XMon, 6 Feb 1995 09:00:00 +0300
XMon, 6 Feb 1995 09:00:00 -0300
XMon, 6 Feb 1995 09:00:00 0400
XMon, 6 Feb 1995 09:00:00 +0400
XMon, 6 Feb 1995 09:00:00 -0400
XMon, 6 Feb 1995 09:00:00 0500
XMon, 6 Feb 1995 09:00:00 +0500
XMon, 6 Feb 1995 09:00:00 -0500
XMon, 6 Feb 1995 09:00:00 0600
XMon, 6 Feb 1995 09:00:00 +0600
XMon, 6 Feb 1995 09:00:00 -0600
XMon, 6 Feb 1995 09:00:00 0700
XMon, 6 Feb 1995 09:00:00 +0700
XMon, 6 Feb 1995 09:00:00 -0700
XMon, 6 Feb 1995 09:00:00 0800
XMon, 6 Feb 1995 09:00:00 +0800
XMon, 6 Feb 1995 09:00:00 -0800
XMon, 6 Feb 1995 09:00:00 0900
XMon, 6 Feb 1995 09:00:00 +0900
XMon, 6 Feb 1995 09:00:00 -0900
XMon, 6 Feb 1995 09:00:00 1000
XMon, 6 Feb 1995 09:00:00 +1000
XMon, 6 Feb 1995 09:00:00 -1000
XMon, 6 Feb 1995 09:00:00 1100
XMon, 6 Feb 1995 09:00:00 +1100
XMon, 6 Feb 1995 09:00:00 -1100
XMon, 6 Feb 1995 09:00:00 1200
XMon, 6 Feb 1995 09:00:00 +1200
XMon, 6 Feb 1995 09:00:00 -1200
XMon, 6 Feb 1995 09:00:00 JST
XMon, 6 Feb 1995 09:00:00 JDT
XMon, 6 Feb 1995 09:00:00 BST
XMon, 6 Feb 1995 09:00:00 NST
XMon, 6 Feb 1995 09:00:00 AST
XMon, 6 Feb 1995 09:00:00 EDT
XMon, 6 Feb 1995 09:00:00 EST
XMon, 6 Feb 1995 09:00:00 EDT
XMon, 6 Feb 1995 09:00:00 CST
XMon, 6 Feb 1995 09:00:00 CDT
XMon, 6 Feb 1995 09:00:00 MST
XMon, 6 Feb 1995 09:00:00 MDT
XMon, 6 Feb 1995 09:00:00 PST
XMon, 6 Feb 1995 09:00:00 PDT
XMon, 6 Feb 1995 09:00:00 YST
XMon, 6 Feb 1995 09:00:00 YDT
XMon, 6 Feb 1995 09:00:00 HST
XMon, 6 Feb 1995 09:00:00 HDT
XMon, 6 Feb 1995 09:00:00 A
XMon, 6 Feb 1995 09:00:00 B
XMon, 6 Feb 1995 09:00:00 C
XMon, 6 Feb 1995 09:00:00 D
XMon, 6 Feb 1995 09:00:00 E
XMon, 6 Feb 1995 09:00:00 F
XMon, 6 Feb 1995 09:00:00 G
XMon, 6 Feb 1995 09:00:00 H
XMon, 6 Feb 1995 09:00:00 I
XMon, 6 Feb 1995 09:00:00 K
XMon, 6 Feb 1995 09:00:00 L
XMon, 6 Feb 1995 09:00:00 M
XMon, 6 Feb 1995 09:00:00 N
XMon, 6 Feb 1995 09:00:00 O
XMon, 6 Feb 1995 09:00:00 P
XMon, 6 Feb 1995 09:00:00 Q
XMon, 6 Feb 1995 09:00:00 R
XMon, 6 Feb 1995 09:00:00 S
XMon, 6 Feb 1995 09:00:00 T
XMon, 6 Feb 1995 09:00:00 U
XMon, 6 Feb 1995 09:00:00 V
XMon, 6 Feb 1995 09:00:00 W
XMon, 6 Feb 1995 09:00:00 X
XMon, 6 Feb 1995 09:00:00 Y
SHAR_EOF
if test 4336 -ne "`wc -c < 'test_input'`"
then
	echo shar: error transmitting "'test_input'" '(should have been 4336  
characters)'
fi
fi # end of overwriting check
echo shar: extracting "'test_output'" '(6148 characters)'
if test -f 'test_output'
then
	echo shar: will not over-write existing file "'test_output'"
else
sed 's/^X//' << \SHAR_EOF > 'test_output'
X6 Feb 1995 09:00:00 AM PST - 792090000
X6 Feb 1995 09:00:00 PST - 792090000
X6 Feb 1995 09:00 AM PST - 792090000
X6 Feb 1995 09:00 PST - 792090000
X6 Feb 1995 09:00:00 AM - 792090000
X6 Feb 1995 09:00:00 - 792090000
X6 Feb 1995 09:00 AM - 792090000
X6 Feb 1995 09:00 - 792090000
X09:00:00 AM PST 6 Feb 1995 - 792090000
X09:00:00 PST 6 Feb 1995 - 792090000
X09:00 AM PST 6 Feb 1995 - 792090000
X09:00 PST 6 Feb 1995 - 792090000
X09:00:00 AM 6 Feb 1995 - 792090000
X09:00:00 6 Feb 1995 - 792090000
X09:00 AM 6 Feb 1995 - 792090000
X09:00 6 Feb 1995 - 792090000
XMon, 6 Feb 1995 09:00:00 AM PST - 792090000
XMon, 6 Feb 1995 09:00:00 PST - 792090000
XMon, 6 Feb 1995 09:00 AM PST - 792090000
XMon, 6 Feb 1995 09:00 PST - 792090000
XMon, 6 Feb 1995 09:00:00 AM - 792090000
XMon, 6 Feb 1995 09:00:00 - 792090000
XMon, 6 Feb 1995 09:00 AM - 792090000
XMon, 6 Feb 1995 09:00 - 792090000
XMon Feb 6 09:00:00 AM PST 1995 - 792090000
XMon Feb 6 09:00:00 PST 1995 - 792090000
XMon Feb 6 09:00 AM PST 1995 - 792090000
XMon Feb 6 09:00 PST 1995 - 792090000
XMon, 6 Feb 1995 09:00:00 AM PST - 792090000
XMon, 6 Feb 1995 09:00:00 PM PST - 792133200
XSun, 6 Feb 1995 09:00:00 PST - 792090000
XSunday, 6 Feb 1995 09:00:00 PST - 792090000
XMon, 6 Feb 1995 09:00:00 PST - 792090000
XMonday, 6 Feb 1995 09:00:00 PST - 792090000
XTue, 6 Feb 1995 09:00:00 PST - 792090000
XTuesday, 6 Feb 1995 09:00:00 PST - 792090000
XWed, 6 Feb 1995 09:00:00 PST - 792090000
XWednesday, 6 Feb 1995 09:00:00 PST - 792090000
XThu, 6 Feb 1995 09:00:00 PST - 792090000
XThursday, 6 Feb 1995 09:00:00 PST - 792090000
XFri, 6 Feb 1995 09:00:00 PST - 792090000
XFriday, 6 Feb 1995 09:00:00 PST - 792090000
XSat, 6 Feb 1995 09:00:00 PST - 792090000
XSaturday, 6 Feb 1995 09:00:00 PST - 792090000
XMon, 6 Jan 1995 09:00:00 PST - 789411600
XMon, 6 January 1995 09:00:00 PST - 789411600
XMon, 6 Feb 1995 09:00:00 PST - 792090000
XMon, 6 February 1995 09:00:00 PST - 792090000
XMon, 6 Mar 1995 09:00:00 PST - 794509200
XMon, 6 March 1995 09:00:00 PST - 794509200
XMon, 6 Apr 1995 09:00:00 PST - 797187600
XMon, 6 April 1995 09:00:00 PST - 797187600
XMon, 6 May 1995 09:00:00 PST - 799779600
XMon, 6 Jun 1995 09:00:00 PST - 802458000
XMon, 6 June 1995 09:00:00 PST - 802458000
XMon, 6 Jul 1995 09:00:00 PST - 805050000
XMon, 6 July 1995 09:00:00 PST - 805050000
XMon, 6 Aug 1995 09:00:00 PST - 807728400
XMon, 6 August 1995 09:00:00 PST - 807728400
XMon, 6 Sep 1995 09:00:00 PST - 810406800
XMon, 6 September 1995 09:00:00 PST - 810406800
XMon, 6 Oct 1995 09:00:00 PST - 812998800
XMon, 6 October 1995 09:00:00 PST - 812998800
XMon, 6 Nov 1995 09:00:00 PST - 815677200
XMon, 6 November 1995 09:00:00 PST - 815677200
XMon, 6 Dec 1995 09:00:00 PST - 818269200
XMon, 6 December 1995 09:00:00 PST - 818269200
XMon, 6 Feb 1995 09:00:00 GMT - 792061200
XMon, 6 Feb 1995 09:00:00 UTC - 792061200
XMon, 6 Feb 1995 09:00:00 UT - 792061200
XMon, 6 Feb 1995 09:00:00 0000 - 792061200
XMon, 6 Feb 1995 09:00:00 +0000 - 792061200
XMon, 6 Feb 1995 09:00:00 -0000 - 792061200
XMon, 6 Feb 1995 09:00:00 0100 - 792057600
XMon, 6 Feb 1995 09:00:00 +0100 - 792057600
XMon, 6 Feb 1995 09:00:00 -0100 - 792064800
XMon, 6 Feb 1995 09:00:00 0200 - 792054000
XMon, 6 Feb 1995 09:00:00 +0200 - 792054000
XMon, 6 Feb 1995 09:00:00 -0200 - 792068400
XMon, 6 Feb 1995 09:00:00 0300 - 792050400
XMon, 6 Feb 1995 09:00:00 +0300 - 792050400
XMon, 6 Feb 1995 09:00:00 -0300 - 792072000
XMon, 6 Feb 1995 09:00:00 0400 - 792046800
XMon, 6 Feb 1995 09:00:00 +0400 - 792046800
XMon, 6 Feb 1995 09:00:00 -0400 - 792075600
XMon, 6 Feb 1995 09:00:00 0500 - 792043200
XMon, 6 Feb 1995 09:00:00 +0500 - 792043200
XMon, 6 Feb 1995 09:00:00 -0500 - 792079200
XMon, 6 Feb 1995 09:00:00 0600 - 792039600
XMon, 6 Feb 1995 09:00:00 +0600 - 792039600
XMon, 6 Feb 1995 09:00:00 -0600 - 792082800
XMon, 6 Feb 1995 09:00:00 0700 - 792036000
XMon, 6 Feb 1995 09:00:00 +0700 - 792036000
XMon, 6 Feb 1995 09:00:00 -0700 - 792086400
XMon, 6 Feb 1995 09:00:00 0800 - 792032400
XMon, 6 Feb 1995 09:00:00 +0800 - 792032400
XMon, 6 Feb 1995 09:00:00 -0800 - 792090000
XMon, 6 Feb 1995 09:00:00 0900 - 792028800
XMon, 6 Feb 1995 09:00:00 +0900 - 792028800
XMon, 6 Feb 1995 09:00:00 -0900 - 792093600
XMon, 6 Feb 1995 09:00:00 1000 - 792025200
XMon, 6 Feb 1995 09:00:00 +1000 - 792025200
XMon, 6 Feb 1995 09:00:00 -1000 - 792097200
XMon, 6 Feb 1995 09:00:00 1100 - 792021600
XMon, 6 Feb 1995 09:00:00 +1100 - 792021600
XMon, 6 Feb 1995 09:00:00 -1100 - 792100800
XMon, 6 Feb 1995 09:00:00 1200 - 792018000
XMon, 6 Feb 1995 09:00:00 +1200 - 792018000
XMon, 6 Feb 1995 09:00:00 -1200 - 792104400
XMon, 6 Feb 1995 09:00:00 JST - 792054000
XMon, 6 Feb 1995 09:00:00 JDT - 792050400
XMon, 6 Feb 1995 09:00:00 BST - 792064800
XMon, 6 Feb 1995 09:00:00 NST - 792073800
XMon, 6 Feb 1995 09:00:00 AST - 792075600
XMon, 6 Feb 1995 09:00:00 EDT - 792072000
XMon, 6 Feb 1995 09:00:00 EST - 792079200
XMon, 6 Feb 1995 09:00:00 EDT - 792072000
XMon, 6 Feb 1995 09:00:00 CST - 792082800
XMon, 6 Feb 1995 09:00:00 CDT - 792079200
XMon, 6 Feb 1995 09:00:00 MST - 792086400
XMon, 6 Feb 1995 09:00:00 MDT - 792082800
XMon, 6 Feb 1995 09:00:00 PST - 792090000
XMon, 6 Feb 1995 09:00:00 PDT - 792086400
XMon, 6 Feb 1995 09:00:00 YST - 792093600
XMon, 6 Feb 1995 09:00:00 YDT - 792090000
XMon, 6 Feb 1995 09:00:00 HST - 792097200
XMon, 6 Feb 1995 09:00:00 HDT - 792093600
XMon, 6 Feb 1995 09:00:00 A - 792064800
XMon, 6 Feb 1995 09:00:00 B - 792068400
XMon, 6 Feb 1995 09:00:00 C - 792072000
XMon, 6 Feb 1995 09:00:00 D - 792075600
XMon, 6 Feb 1995 09:00:00 E - 792079200
XMon, 6 Feb 1995 09:00:00 F - 792082800
XMon, 6 Feb 1995 09:00:00 G - 792086400
XMon, 6 Feb 1995 09:00:00 H - 792090000
XMon, 6 Feb 1995 09:00:00 I - 792093600
XMon, 6 Feb 1995 09:00:00 K - 792097200
XMon, 6 Feb 1995 09:00:00 L - 792100800
XMon, 6 Feb 1995 09:00:00 M - 792104400
XMon, 6 Feb 1995 09:00:00 N - 792064800
XMon, 6 Feb 1995 09:00:00 O - 792068400
XMon, 6 Feb 1995 09:00:00 P - 792072000
XMon, 6 Feb 1995 09:00:00 Q - 792075600
XMon, 6 Feb 1995 09:00:00 R - 792079200
XMon, 6 Feb 1995 09:00:00 S - 792082800
XMon, 6 Feb 1995 09:00:00 T - 792086400
XMon, 6 Feb 1995 09:00:00 U - 792090000
XMon, 6 Feb 1995 09:00:00 V - 792093600
XMon, 6 Feb 1995 09:00:00 W - 792097200
XMon, 6 Feb 1995 09:00:00 X - 792100800
XMon, 6 Feb 1995 09:00:00 Y - 792104400
SHAR_EOF
if test 6148 -ne "`wc -c < 'test_output'`"
then
	echo shar: error transmitting "'test_output'" '(should have been 6148  
characters)'
fi
fi # end of overwriting check
echo shar: extracting "'xmit_time.1'" '(989 characters)'
if test -f 'xmit_time.1'
then
	echo shar: will not over-write existing file "'xmit_time.1'"
else
sed 's/^X//' << \SHAR_EOF > 'xmit_time.1'
X.TH xmit_time 1 "11 February 1995"
X.SH NAME
Xxmit_time - figure transmission time of netnews articles
X.SH SYNOPSIS
X.B xmit_time
X.IR file ...
X.SH DESCRIPTION
X.PP
XGiven a set of netnews article filenames as arguments, looks in each file for
Xa netnews-format Date: line.
XAlso looks at the last-modified time of the file.
XThe difference between the two is how long it took that article to
Xtravel from the poster's site to your site, and that number (in seconds)
Xis written to stdout.
X.SH "SEE ALSO"
Xdate_sort(1), date_order(1), deltime(1), date_parse(3)
X.SH AUTHOR
XCopyright (C) 1995 by Jef Poskanzer.
X.\" Permission to use, copy, modify, and distribute this software and its
X.\" documentation for any purpose and without fee is hereby granted, provided
X.\" that the above copyright notice appear in all copies and that both that
X.\" copyright notice and this permission notice appear in supporting
X.\" documentation.  This software is provided "as is" without express or
X.\" implied warranty.
SHAR_EOF
if test 989 -ne "`wc -c < 'xmit_time.1'`"
then
	echo shar: error transmitting "'xmit_time.1'" '(should have been 989  
characters)'
fi
fi # end of overwriting check
echo shar: extracting "'xmit_time.c'" '(1975 characters)'
if test -f 'xmit_time.c'
then
	echo shar: will not over-write existing file "'xmit_time.c'"
else
sed 's/^X//' << \SHAR_EOF > 'xmit_time.c'
X/* xmit_time - figure out transmission time of netnews articles
X**
X** Copyright (C) 1995 by Jef Poskanzer <jef at netcom.com>.
X**
X** Permission to use, copy, modify, and distribute this software and its
X** documentation for any purpose and without fee is hereby granted, provided
X** that the above copyright notice appear in all copies and that both that
X** copyright notice and this permission notice appear in supporting
X** documentation.  This software is provided "as is" without express or
X** implied warranty.
X*/
X
X#include <stdio.h>
X#include <string.h>
X#include <sys/stat.h>
X#include <time.h>
X
Xextern time_t date_parse();
X
Xstatic void usage();
Xstatic void do_file();
X
Xstatic char* argv0;
X
Xvoid
Xmain( argc, argv )
X    int argc;
X    char* argv[];
X    {
X    int argn;
X
X    argv0 = argv[0];
X    argn = 1;
X    if ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
X	usage();
X
X    while ( argn < argc )
X	{
X	do_file( argv[argn] );
X	++argn;
X	}
X
X    exit( 0 );
X    }
X
Xstatic void
Xusage()
X    {
X    (void) fprintf( stderr, "usage:  %s file ...\n", argv0 );
X    exit( 1 );
X    }
X
Xstatic void
Xdo_file( name )
X    char* name;
X    {
X    struct stat sb;
X    time_t posted, arrived;
X    FILE* f;
X    char line[30000];
X
X    f = fopen( name, "r" );
X    if ( f == (FILE*) 0 )
X	{
X	perror( name );
X	return;
X	}
X
X    if ( fstat( fileno( f ), &sb ) < 0 )
X	{
X	perror( name );
X	(void) fclose( f );
X	return;
X	}
X    arrived = sb.st_mtime;
X
X    for (;;)
X	{
X	if ( fgets( line, sizeof(line), f ) == (char*) 0 )
X	    break;
X	if ( line[0] == '\n' )
X	    break;
X	if ( strncmp( line, "Date:", 5 ) == 0 )
X	    {
X	    (void) fclose( f );
X	    posted = date_parse( &line[5] );
X	    if ( posted == (time_t) -1 )
X		(void) fprintf(
X		    stderr, "%s: unparsable date in %s - %s",
X		    argv0, name, &line[5] );
X	    else
X		(void) printf( "%d\n", arrived - posted );
X	    return;
X	    }
X	}
X
X    (void) fprintf( stderr, "%s: no Date: line found in %s\n", argv0, name );
X    (void) fclose( f );
X    }
X
X
SHAR_EOF
if test 1975 -ne "`wc -c < 'xmit_time.c'`"
then
	echo shar: error transmitting "'xmit_time.c'" '(should have been 1975  
characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0



More information about the tz mailing list