/* Convert an ISO8601:1988 week number to the date of the start of
 * that week (i.e. the Monday)
 *
 * Andrew Benham, June 1998
 */

#include <stdio.h>
#include <time.h>
#include <string.h>
#include <stdlib.h>

int main(int argc, char **argv)
{
	char *cp,tmp[5];
	int year,week;
	struct tm tm;
	time_t t;

	/* Check the single parameter is valid, e.g. 1998W27 */
	if (argc != 2){
		fprintf(stderr,"Syntax: whenis yyyyWww\n");
		return 1;
	}
	if ((strlen(argv[1]) != 7) || (argv[1][4] != 'W')) {
		fprintf(stderr,"Syntax error: need yyyyWww\n");
		return 1;
	}

	/* Extract the year and week numbers */
	strncpy(tmp,argv[1],4);
	year=atoi(tmp);
	cp = argv[1]+5;
	strcpy(tmp,cp);
	week=atoi(tmp);

	/* Range checks */
	if (year < 1970 || year > 2037) {
		fprintf(stderr,"Year %04d out of range\n",year);
		return 1;
	}
	if (week < 1 || week > 53) {
		fprintf(stderr,"Week %02d out of range\n",week);
		return 1;
	}

	/* ISO8601:1988 week numbers guarantee that 4 Jan is in week 01
	 *
	 * Set the struct tm up with 4 January */
	tm.tm_year=year-1900;
	tm.tm_mon=0;
	tm.tm_mday=4;
	tm.tm_hour=12;
	tm.tm_min=0;
	tm.tm_sec=0;
	tm.tm_isdst=-1;

	/* Now bump the day of the month up by (1 minus the week number)
	 * number of weeks
	 */
	tm.tm_mday+=(7*(week-1));

	/* Call mktime() to fixup the date fields, and set day of week */
	t=mktime(&tm);

	/* Move Sunday to the end of the week */
	if (tm.tm_wday == 0) {
		tm.tm_wday = 7;
	}

	/* Drop the day of the month back to the Monday of the week */
	tm.tm_mday -= (tm.tm_wday -1);

	/* Call mktime() to fixup the date fields again */
	t=mktime(&tm);

	/* Check whether week 53 is valid for the given year */
	if (week == 53) {

		/* Valid week 53s start on 27 or 28 December */
		if ((tm.tm_mon != 11) || (tm.tm_mday != 27 && tm.tm_mday != 28)) {

			/* If not valid, return -1/-1/year
			 *
			 * The month number gets incremented in the printf()
			 */
			tm.tm_mday=-1;
			tm.tm_mon=-2;
		}
	}
	printf("%02d/%02d/%04d\n",tm.tm_mday,1+tm.tm_mon,1900+tm.tm_year);


	return 0;
}
