#include "args.h"
#include "config.h"
/*
 * Copyright (c) 1986, 2014 by The Trustees of Columbia University in
 * the City of New York.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *  + Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 *  + Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 *  + Neither the name of Columbia University nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 */

#ifndef lint
static char *rcsid = "$Header: /f/src2/encore.bin/cucca/mm/tarring-it-up/RCS/dt.c,v 2.1 90/10/04 18:24:01 melissa Exp $";
#endif

#include "mm.h"
#include "keytab.h"

static int lookupzone ARGS((char *z));
static int whatmonth ARGS((char *mon));
static time_t mkdate ARGS((int yr, int mon, int day, int hr, int min,
			 int sec, char *z));

#ifdef howmany
#undef howmany
#endif

static const char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
				"Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
#if 0					/* no longer used */
static int monthlens[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
#endif

#if defined(HAVE_GNU_LINUX)
#define timezone timezone_
struct timezone {
    int ignored;
};
#endif


static struct tmz {
    const char *name;
    const char *dstname;
    int minwest;
} zones[] = {
    { "GMT", "GMT",       0*60 },
    { "AST", "ADT",       4*60 },
    { "EST", "EDT",       5*60 },
    { "CST", "CDT",       6*60 },
    { "MST", "MDT",       7*60 },
    { "PST", "PDT",       8*60 },
    { "YST", "YDT",       9*60 },
    { "HST", "HDT",      10*60 },
    { "BST", "BDT",      11*60 },
    { "WET", "WET DST",   0*60 },
    { "MET", "MET DST",  -1*60 },
    { "EET", "EET DST",  -2*60 },
    { "EST", "EST",     -10*60 },
    { "CST", "CST", -(9*60+30) },
    { "WST", "WST",      -8*60 },
};
static int
#if HAVE_STDC
lookupzone(char *z)
#else /* K&R style */
lookupzone(z)
char *z;
#endif /* HAVE_STDC */
{
    int i;
    for(i = 0; i < sizeof(zones)/sizeof(struct tmz); i++) {
	if (ustrcmp(z,zones[i].name) == 0)
	    return(zones[i].minwest);
	if (ustrcmp(z,zones[i].dstname) == 0)
	    return(zones[i].minwest-60);
    }
    return(-1);
}

time_t
#if HAVE_STDC
mbox_date(const char *str)
#else /* K&R style */
mbox_date(str)
const char *str;
#endif /* HAVE_STDC */
{
    int n;
    time_t t;
    char mon[4],dow[4];
    int day, month, year, hr, min, sec;

    n = sscanf(str, "%3s %3s %2d %2d:%2d:%2d %4d\n",
	       dow,mon,&day,&hr,&min,&sec,&year);
    if (n != 7)
	return(stringtotime(str));
    if ((month = whatmonth(mon)) == -1)
	return(stringtotime(str));
    t = mkdate(year,month,day,hr,min,sec,NULL);
    return(t);
}

time_t
#if HAVE_STDC
mtxt_date(const char *str)
#else /* K&R style */
mtxt_date(str)
const char *str;
#endif /* HAVE_STDC */
{
    int n;
    time_t t;
    char mon[4],tz[10];
    int day, month, year, hr, min, sec;

    n = sscanf(str, "%2d-%3s-%d %2d:%2d:%d-%3s\n",&day,mon,&year,&hr,&min,
	       &sec,tz);
    if (n != 7)
	return(stringtotime(str));
    if ((month = whatmonth(mon)) == -1)
	return(stringtotime(str));
    if (year < 100) year += 1900;
    t = mkdate(year,month,day,hr,min,sec,tz);
    return(t);
}

time_t
#if HAVE_STDC
babyl_date(const char *str)
#else /* K&R style */
babyl_date(str)
const char *str;
#endif /* HAVE_STDC */
{
    int n;
    char mon[4],tz[4],dow[4];
    int day, month, year, hr, min, sec;

    n = sscanf(str, "%3s, %2d %3s %d %2d:%2d:%2d %3s\n",
	       dow,&day,mon,&year,&hr,&min,&sec,tz);
    if (n == 8) {
	if ((month = whatmonth(mon)) == -1)
	    return(stringtotime(str));
	if (year < 100) year += 1900;
	return(mkdate(year,month,day,hr,min,sec,tz));
    }
    n = sscanf(str, "%3s, %2d %3s %d, %2d:%2d:%2d %3s\n",
	       dow,&day,mon,&year,&hr,&min,&sec,tz);
    if (n == 8) {
	if ((month = whatmonth(mon)) == -1)
	    return(stringtotime(str));
	if (year < 100) year += 1900;
	return(mkdate(year,month,day,hr,min,sec,tz));
    }
    n = sscanf(str, "%3s %2d %3s %d %2d:%2d:%2d %3s\n",
	       dow,&day,mon,&year,&hr,&min,&sec,tz);
    if (n == 8)  {
	if ((month = whatmonth(mon)) == -1)
	    return(stringtotime(str));
	if (year < 100) year += 1900;
	return(mkdate(year,month,day,hr,min,sec,tz));
    }
    n = sscanf(str, "%3s, %2d %3s %d %2d:%2d %3s\n",
	       dow,&day,mon,&year,&hr,&min,tz);
    if (n == 7) {
	if ((month = whatmonth(mon)) == -1)
	    return(stringtotime(str));
	if (year < 100) year += 1900;
	return(mkdate(year,month,day,hr,min,0,tz));
    }
    n = sscanf(str, "%3s %2d %3s %d %2d:%2d %3s\n",
	       dow,&day,mon,&year,&hr,&min,tz);
    if (n == 7) {
	if ((month = whatmonth(mon)) == -1)
	    return(stringtotime(str));
	if (year < 100) year += 1900;
	return(mkdate(year,month,day,hr,min,0,tz));
    }
    return(stringtotime(str));
}
static int
#if HAVE_STDC
whatmonth(char *mon)
#else /* K&R style */
whatmonth(mon)
char *mon;
#endif /* HAVE_STDC */
{
    int i;
    for(i = 0; i < 12; i++) {
	if (strcmp(months[i], mon) == 0) {
	    return(i);
	}
    }
    return(-1);
}

#ifdef SYSV
extern long timezone;
#endif

static time_t
#if HAVE_STDC
mkdate(int yr, int mon, int day, int hr, int min, int sec, char *z)
#else /* K&R style */
mkdate(yr,mon,day,hr,min,sec,z)
int yr,mon,day,hr,min,sec;
char *z;
#endif /* HAVE_STDC */
{
    time_t t;
    datime dt;
    struct tm *tm;
#ifdef BSD
    struct timeval tp;
    struct timezone tz;
#endif
    int zone;

    if (z)
	zone = lookupzone(z);
    else
	zone = -1;
#ifdef BSD
#if __solaris
    gettimeofday(&tp);
#else
    gettimeofday(&tp, &tz);
#endif
#endif
    dt._dtsec = sec;
    dt._dtmin = min;
    dt._dthr = hr;
    dt._dtday = day-1;
    dt._dtmon = mon;
    dt._dtyr = yr;
    dt._dtdst = 0;
    dt._dttz = 0;
    t = datime_to_time(&dt);
    tm = localtime(&t);
#if SYSV
    asctime(tm);
    t += (zone != -1) ? zone*60 : timezone;
#endif
#if BSD
#if __solaris
    t += (zone != -1) ? zone*60 : timezone;
#elif defined(HAVE_GNU_LINUX)
    t += (zone != -1) ? zone*60 : 0;
#else
    t += (zone != -1) ? zone*60 : tz.tz_minuteswest*60;
#endif
#endif
    if ((zone == -1) && (tm->tm_isdst)) t -= 3600;
    return(t);
}

#ifdef undef
main() {
    mbox_date("Jan  1 00:00:00 1970");
    mtxt_date("01-Jan-70 00:00:00-GMT");
    babyl_date("Thu, 1 Jan 70 00:00:00 EST");
    mbox_date("Jun  1 00:00:00 1970");	/* some IN dst */
    mtxt_date("01-Jun-70 00:00:00-GMT");
    babyl_date("Thu, 1 Jun 70 00:00:00 EST");
}

#endif
