/*
command line to compile:

	gcc -std=gnu99 -o ~/bin/time_t time_t.c
*/
#undef _NO_OLDNAMES
#undef RC_INVOKED
#include <time.h>
//extern void tzset(void);
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

int main(int argc, char *argv[])
{
	int i, rc = 0, tz_expected = 0;
	long my_tz;

	tzset();
	my_tz = -timezone; // daylight is not meaningful

	if (argc <= 1 || strcmp(argv[1], "-h") == 0)
	{
		printf(
			"Arguments passed as dates, yyyy-mm-dd[Thh:mm:ss], yy.mm.dd [hh:mm:ss],\n"
			"dd/mm/yyyy [hh:mm:ss], \"now\", or number, are echoed in three formats.\n"
			"Numbers with leading 0 or 0x are octal or hex, except after punctuation\n"
			"-z 3600 sets timezone 1 hour West of UTC, default is -(%ld - %d hour DST).\n"
			"-Z 1 is the same as -z 3600.\n",
				timezone, daylight);
		return 0;
	}

	for (i = 1; i < argc; ++i)
	{
		char *t = NULL;
		unsigned long ul;
		if (tz_expected == 0 && strcasecmp(argv[i], "now") == 0)
			ul = time(0);
		else
			ul = strtoul(argv[i], &t, 0);
		int rtc = 1;

		if (tz_expected)
		{
			my_tz = ul * (long)tz_expected;
			tz_expected = 0;
			continue;
		}
		else if (strcmp(argv[i], "-z") == 0)
		{
			tz_expected = 1;
			continue;
		}
		else if (strcmp(argv[i], "-Z") == 0)
		{
			tz_expected = 3600;
			continue;
		}

		if (ul > 0 && t && ispunct(*t)) // convert from yyyy-mm-ddThh:mm:ss
		{
			struct tm tm;
			char *p = t + 1;
			unsigned long first = ul, last = 0;
			memset(&tm, 0, sizeof tm);

			ul = strtoul(p, &t, 10);
			if (ul > 0 && ispunct(*t))
			{
				tm.tm_mon = ul - 1;
				p = t + 1;
				ul = strtoul(p, &t, 10);
				if (ul > 0)
				{
					last = ul;
					if (*t) // can be 'T', space, or whatever
					{
						p = t + 1;
						ul = strtoul(p, &t, 10);
						if (*t == ':')
						{
							tm.tm_hour = (int)ul;
							p = t + 1;
							ul = strtoul(p, &t, 10);
							if (*t == ':')
							{
								tm.tm_min = (int)ul;
								p = t + 1;
								ul = strtoul(p, &t, 10);
								if (*t == 0)
									tm.tm_sec = (int)ul;
							}
						}
					}
				}
			}
			if (last < 1900)
			{
				tm.tm_mday = (int)last;
				if (first > 1900)
					first -= 1900;
				else
					first += 100;
				tm.tm_year = (int)first;
			}
			else
			{
				tm.tm_mday = (int)first;
				tm.tm_year = (int)last - 1900;
			}
			ul = mktime(&tm);    // convert to localtime w/o DST
			if ((long)ul != -1L) // then adjust timezone
				ul -= timezone;
		}

		if ((long)ul < 0 || t && *t != 0)
		{
			fprintf(stderr, "invalid argument %s\n", argv[i]);
		}
		else
		{
			time_t tt = (time_t)(ul + my_tz);
			struct tm *t = gmtime(&tt);
			if (t)
			{
				char stz[80];
				struct tm tm = *t;

				if (my_tz)
					sprintf(stz, "%+02ld:%02ld", my_tz /3600L, my_tz%3600L);
				else
					strcpy(stz, "Z");

				fprintf(stdout, // RFC 3339
					"%#lx = %lu = %04d-%02d-%02dT%02d:%02d:%02d%s (%s)\n",
					ul, ul,
					tm.tm_year + 1900,
					tm.tm_mon+1,
					tm.tm_mday,
					tm.tm_hour,
					tm.tm_min,
					tm.tm_sec,
					stz,
					argv[i]);
				rtc = 0;
			}
		}
		rc += rtc;
	}
	if (rc)
		fprintf(stderr, "exiting with rtc=%d\n", rc);
	return rc;
}
