Exemple #1
0
void make_answer(int* ans) 
{
	int y, m, d;
	y = 1 + rand() % MAX_YEAR;
	m = 1 + rand() % 12;
	d = monthdays(y, m);
	ans[0] = y;
	ans[1] = m;
	ans[2] = d;
}
int get_first_month(int year, int month)
{
	const int weeknum[7] = {1,2,3,4,5,6,0}; 			//数组的作用是对应不同余数的星期

	int weeksum = yeardays(year) + monthdays(year,month) + 1; 				//计算这个月第一天到基准日的天数

	int week = weeksum % 7;   							//计算这些天的星期余数

	return weeknum[week];

}
int weekday(int year, int month, int day) 		//计算当前日期到基准日的星期
{
	const int weeknum[7] = {1,2,3,4,5,6,0};

	int weeksum = yeardays(year) + monthdays(year,month)+ day;

	int week = weeksum % 7;

	return weeknum[week];

}
Exemple #4
0
/*
 * Parse an RFC 3339 = ISO 8601 format date-time string.
 * Returns: number of characters in @s consumed, or -1 on error.
 */
EXPORTED int time_from_iso8601(const char *s, time_t *tp)
{
    const char *origs = s;
    struct tm exp;
    int n, tm_off;

    /* parse the ISO 8601 date/time */
    /* XXX should use strptime ? */
    memset(&exp, 0, sizeof(struct tm));
    n = sscanf(s, "%4d-%2d-%2dT%2d:%2d:%2d",
               &exp.tm_year, &exp.tm_mon, &exp.tm_mday,
               &exp.tm_hour, &exp.tm_min, &exp.tm_sec);
    if (n != 6)
        return -1;

    s += 19;
    if (*s == '.') {
        /* skip fractional secs */
        while (Uisdigit(*(++s)));
    }

    /* handle offset */
    switch (*s++) {
    case 'Z': tm_off = 0; break;
    case '-': tm_off = -1; break;
    case '+': tm_off = 1; break;
    default: return -1;
    }
    if (tm_off) {
        int tm_houroff, tm_minoff;

        n = sscanf(s, "%2d:%2d", &tm_houroff, &tm_minoff);
        if (n != 2)
            return -1;
        tm_off *= 60 * (60 * tm_houroff + tm_minoff);
        s += 5;
    }

    exp.tm_year -= 1900; /* normalize to years since 1900 */
    exp.tm_mon--; /* normalize to months since January */

    /* sanity check the date/time (including leap day & second) */
    if (exp.tm_year < 70 || exp.tm_mon < 0 || exp.tm_mon > 11 ||
        exp.tm_mday < 1 ||
        exp.tm_mday > monthdays(exp.tm_year, exp.tm_mon) ||
        exp.tm_hour > 23 || exp.tm_min > 59 || exp.tm_sec > 60) {
        return -1;
    }

    /* normalize to GMT */
    *tp = mkgmtime(&exp) - tm_off;
    return s - origs;
}
int returnMonthDiff(int *arr, int a, int b)
{
	int i, sum = 0, max = 0;
	if (a < b){
		i = a; max = b;
	}
	else{
		i = b; max = a;
	}
	while (i <= max)
	{
		sum = sum + monthdays(arr, i);
		i++;
	}
	return sum;

}
Exemple #6
0
int main(void)
{
	int total = 0;
	int weekday = 2; // 1901/1/1 == Tuesday
	
	for (int year = 1901; year <= 2000; year++)
	{
		for (int month = 0; month < 12; month++)
		{
			if (weekday == 0)
				total++;
			weekday = (weekday + monthdays(year, month)) % 7;
		}
	}
	
	printf("%d\n", total);
	return 0;
}
BOOL EVAL::EvalFunction(INT nFunction, INT argc, double * argv, double * pValue)
{
	switch( nFunction ) {

	case EVAL_FUNCTION_ABS:
		if( argc == 1 ) { * pValue = fabs( argv[0] ); return TRUE; }
		break;

	case EVAL_FUNCTION_MOD:
		if( argc == 2 ) { * pValue = fmod( argv[0], argv[1] ); return TRUE; }
		break;

	case EVAL_FUNCTION_CEIL:
		if( argc == 1 ) { * pValue = ceil( argv[0] ); return TRUE; }
		break;

	case EVAL_FUNCTION_FLOOR:
		if( argc == 1 ) { * pValue = floor( argv[0] ); return TRUE; }
		break;

	case EVAL_FUNCTION_ROUND:
		if( argc == 1 ) { * pValue = floor( argv[0] + 0.5 ); return TRUE; }
		break;

	case EVAL_FUNCTION_MIN:
		if( argc == 2 ) { * pValue = argv[0] < argv[1] ? argv[0] : argv[1]; return TRUE; }
		break;

	case EVAL_FUNCTION_MAX:
		if( argc == 2 ) { * pValue = argv[0] > argv[1] ? argv[0] : argv[1]; return TRUE; }
		break;

	case EVAL_FUNCTION_ACOS:
		if( argc == 1 ) { * pValue = acos(argv[0]); return TRUE; }
		break;

	case EVAL_FUNCTION_ASIN:
		if( argc == 1 ) { * pValue = asin(argv[0]); return TRUE; }
		break;

	case EVAL_FUNCTION_ATAN:
		if( argc == 1 ) { * pValue = atan(argv[0]); return TRUE; }
		break;

	case EVAL_FUNCTION_ATAN2:
		if( argc == 2 ) { * pValue = atan2(argv[0], argv[1]); return TRUE; }
		break;

	case EVAL_FUNCTION_COS:
		if( argc == 1 ) { * pValue = cos(argv[0]); return TRUE; }
		break;

	case EVAL_FUNCTION_SIN:
		if( argc == 1 ) { * pValue = sin(argv[0]); return TRUE; }
		break;

	case EVAL_FUNCTION_TAN:
		if( argc == 1 ) { * pValue = tan(argv[0]); return TRUE; }
		break;

	case EVAL_FUNCTION_COSH:
		if( argc == 1 ) { * pValue = cosh(argv[0]); return TRUE; }
		break;

	case EVAL_FUNCTION_SINH:
		if( argc == 1 ) { * pValue = sinh(argv[0]); return TRUE; }
		break;

	case EVAL_FUNCTION_TANH:
		if( argc == 1 ) { * pValue = tanh(argv[0]); return TRUE; }
		break;

	case EVAL_FUNCTION_EXP:
		if( argc == 1 ) { * pValue = exp(argv[0]); return TRUE; }
		break;

	case EVAL_FUNCTION_LOG:
		if( argc == 1 ) { * pValue = log(argv[0]); return TRUE; }
		break;

	case EVAL_FUNCTION_LOG10:
		if( argc == 1 ) { * pValue = log10(argv[0]); return TRUE; }
		break;

	case EVAL_FUNCTION_POW:
		if( argc == 2 ) { * pValue = pow(argv[0], argv[1]); return TRUE; }
		break;

	case EVAL_FUNCTION_SQR:
		if( argc == 1 ) { * pValue = argv[0] * argv[0]; return TRUE; }
		break;

	case EVAL_FUNCTION_SQRT:
		if( argc == 1 ) { * pValue = sqrt(argv[0]); return TRUE; }
		break;

	case EVAL_FUNCTION_TODAY:
		if( argc == 0 ) { * pValue = (double)today(); return TRUE; }
		break;

	case EVAL_FUNCTION_YEARDAYS:
		if( argc == 1 ) { * pValue = (double)yeardays((int)argv[0]); return TRUE; }
		break;

	case EVAL_FUNCTION_MONTHDAYS:
		if( argc == 2 ) { * pValue = (double)monthdays((int)argv[0], (int)argv[1]); return TRUE; }
		break;

	case EVAL_FUNCTION_DATE2DAYS:
		if( argc == 1 ) { * pValue = (double)date2days((int)argv[0]); return TRUE; }
		break;

	case EVAL_FUNCTION_DAYS2DATE:
		if( argc == 1 ) { * pValue = (double)days2date((int)argv[0]); return TRUE; }
		break;

	case EVAL_FUNCTION_EOMDAY:
		if( argc == 2 ) { * pValue = (double)eomday((int)argv[0], (int)argv[1]); return TRUE; }
		break;

	case EVAL_FUNCTION_EOMDATE:
		if( argc == 2 ) { * pValue = (double)eomdate((int)argv[0], (int)argv[1]); return TRUE; }
		break;

	case EVAL_FUNCTION_WEEKDAY:
		if( argc == 1 ) { * pValue = (double)weekday((int)argv[0]); return TRUE; }
		break;

	case EVAL_FUNCTION_ISBIZDATE:
		if( argc == 1 ) { * pValue = (double)isbizdate((int)argv[0], HDC_SUNSAT  ); return TRUE; }
		if( argc == 2 ) { * pValue = (double)isbizdate((int)argv[0], (int)argv[1]); return TRUE; }
		break;

	case EVAL_FUNCTION_NBIZDATE:
		if( argc == 1 ) { * pValue = (double)nbizdate((int)argv[0], HDC_SUNSAT  ); return TRUE; }
		if( argc == 2 ) { * pValue = (double)nbizdate((int)argv[0], (int)argv[1]); return TRUE; }
		break;

	case EVAL_FUNCTION_PBIZDATE:
		if( argc == 1 ) { * pValue = (double)pbizdate((int)argv[0], HDC_SUNSAT  ); return TRUE; }
		if( argc == 2 ) { * pValue = (double)pbizdate((int)argv[0], (int)argv[1]); return TRUE; }
		break;

	case EVAL_FUNCTION_ADDDAYS:
		if( argc == 2 ) { * pValue = (double)adddays((int)argv[0], (int)argv[1]); return TRUE; }
		break;

	case EVAL_FUNCTION_ADDMONTHS:
		if( argc == 2 ) { * pValue = (double)addmonths((int)argv[0], (int)argv[1], EMR_ACTUAL  ); return TRUE; }
		if( argc == 3 ) { * pValue = (double)addmonths((int)argv[0], (int)argv[1], (int)argv[2]); return TRUE; }
		break;

	case EVAL_FUNCTION_ADDTERMS:
		if( argc == 3 ) { * pValue = (double)addterms((int)argv[0], (int)argv[1], (int)argv[2], EMR_ACTUAL  ); return TRUE; }
		if( argc == 4 ) { * pValue = (double)addterms((int)argv[0], (int)argv[1], (int)argv[2], (int)argv[3]); return TRUE; }
		break;

	case EVAL_FUNCTION_DAYS360:
		if( argc == 2 ) { * pValue = (double)days360((int)argv[0], (int)argv[1], 0 /* USA */ ); return TRUE; }
		if( argc == 3 ) { * pValue = (double)days360((int)argv[0], (int)argv[1], (int)argv[2]); return TRUE; }
		break;

	case EVAL_FUNCTION_DAYS365:
		if( argc == 2 ) { * pValue = (double)days365((int)argv[0], (int)argv[1]); return TRUE; }
		break;

	case EVAL_FUNCTION_DAYSACT:
		if( argc == 2 ) { * pValue = (double)daysact((int)argv[0], (int)argv[1]); return TRUE; }
		break;

	case EVAL_FUNCTION_DAYSBET:
		if( argc == 2 ) { * pValue = (double)daysbet((int)argv[0], (int)argv[1], DCB_ACTACT  ); return TRUE; }
		if( argc == 3 ) { * pValue = (double)daysbet((int)argv[0], (int)argv[1], (int)argv[2]); return TRUE; }
		break;

	case EVAL_FUNCTION_MONTHSBET:
		if( argc == 2 ) { * pValue = (double)monthsbet((int)argv[0], (int)argv[1]); return TRUE; }
		break;

	case EVAL_FUNCTION_TERMSBET:
		if( argc == 3 ) { * pValue = (double)termsbet((int)argv[0], (int)argv[1], (int)argv[2]); return TRUE; }
		break;

	case EVAL_FUNCTION_TERMFRAC:
		if( argc == 3 ) { * pValue = termfrac((int)argv[0], (int)argv[1], (int)argv[2], DCB_ACTACT,   EMR_ACTUAL  ); return TRUE; }
		if( argc == 4 ) { * pValue = termfrac((int)argv[0], (int)argv[1], (int)argv[2], (int)argv[3], EMR_ACTUAL  ); return TRUE; }
		if( argc == 5 ) { * pValue = termfrac((int)argv[0], (int)argv[1], (int)argv[2], (int)argv[3], (int)argv[4]); return TRUE; }
		break;

	case EVAL_FUNCTION_YEARFRAC:
		if( argc == 2 ) { * pValue = yearfrac((int)argv[0], (int)argv[1], DCB_ACTACT,   EMR_ACTUAL  ); return TRUE; }
		if( argc == 3 ) { * pValue = yearfrac((int)argv[0], (int)argv[1], (int)argv[2], EMR_ACTUAL  ); return TRUE; }
		if( argc == 4 ) { * pValue = yearfrac((int)argv[0], (int)argv[1], (int)argv[2], (int)argv[3]); return TRUE; }
		break;

	}

	return FALSE;
}
Exemple #8
0
int main(int argc, char* argv[])
{
	int y1, m1, y2, m2;
	int ans[3];
	int input[3];
	int* records;
	int max_trial;
	int i, j;

	srand(time(NULL));
	make_answer(ans);

	max_trial = (int)(log2(ans[0]) + log2(ans[1]) + log2(ans[2]));
	records = (int*)malloc(sizeof(int)*3*max_trial);

	printf("日付あてゲーム\n");
	printf("正解の年/月/日を推測してください\n");
	printf("年は 1 ~ %d の間です\n", MAX_YEAR);

	printf("答え: %5d 年 %2d 月 %2d 日\n", ans[0], ans[1], ans[2]);
	for (i = 0; i < max_trial; i++) {
		printf("%d 回目 (残り %d 回)\n", i+1, max_trial-i);
		while (1) {
			printf("年: "); 
			scanf("%d", input);
			if (input[0] < 1 || input[0] > MAX_YEAR) 
				printf("そんな年ねーよ\n");
			else
				break;
		}

		while (1) {
			printf("月: "); 
			scanf("%d", input+1);
			if (input[1] < 1 || input[1] > 12) 
				printf("そんな月ねーよ\n");
			else
				break;
		}

		while (1) {
			printf("日: "); 
			scanf("%d", input+2);
			if (input[2] < 1 || input[2] > monthdays(input[0], input[1])) 
				printf("そんな日ねーよ\n");
			else
				break;
		}

		records[i] = input[0];
		records[i+1] = input[1];
		records[i+2] = input[2];

		int chk = chk_answer(ans, input);
		if (chk == 0) {
			printf("正解!\n");
			break;
		}
		printf("不正解...\n");
	}

	printf("入力の履歴:\n");
	for (j = 0; j <= i; j++) {
		printf("%d 回目\n", j+1);
		printf("%5d 年 %2d 月 %2d 日\n", records[j], records[j+1], records[j+2]);
		printf("正解との差\n");
		printf("%5d, %2d, %2d\n", ans[0]-records[j], ans[1]-records[1], ans[2]-records[2]);
	}

	free(records);
	return 0;
}
Exemple #9
0
/*
 * Parse a string in IMAP date-time format (and some more
 * obscure legacy formats too) to a time_t.  Parses both
 * date and time parts.
 *
 * Specific formats accepted are listed below.  Note that only
 * the first two are compliant with RFC3501, the remainder
 * are legacy formats.  Note that the " quotes are not part
 * of the format, they're just used in this comment to show
 * where the leading spaces are.
 *
 *  "dd-mmm-yyyy HH:MM:SS zzzzz"
 *  " d-mmm-yyyy HH:MM:SS zzzzz"
 *  "dd-mmm-yy HH:MM:SS-z"
 *  " d-mmm-yy HH:MM:SS-z"
 *  "dd-mmm-yy HH:MM:SS-zz"
 *  " d-mmm-yy HH:MM:SS-zz"
 *  "dd-mmm-yy HH:MM:SS-zzz"
 *  " d-mmm-yy HH:MM:SS-zzz"
 *
 * where:
 *  dd  is the day-of-month between 1 and 31 inclusive.
 * mmm  is the three-letter abbreviation for the English
 *      month name (case insensitive).
 * yy   is the 2 digit year, between 00 (the year 1900)
 *      and 99 (the year 1999) inclusive.
 * yyyy is the 4 digit year, between 1900 and disaster
 *      (31b time_t wrapping in 2038 is not handled, sorry).
 * HH   is the hour, zero padded, between 00 and 23 inclusive.
 * MM   is the minute, zero padded, between 00 and 59 inclusive.
 * MM   is the second, zero padded, between 00 and 60 inclusive
 *      (to account for leap seconds).
 * z    is a US military style single character time zone.
 *          A (Alpha) is +0100 ... I (India) is +0900
 *          J (Juliet) is not defined
 *          K (Kilo) is +1000 ... M (Mike) is +1200
 *          N (November) is -0100 ... Y (Yankee) is -1200
 *          Z (Zulu) is UTC
 * zz   is the case-insensitive string "UT", denoting UTC time.
 * zzz  is a three-character case insensitive North American
 *      time zone name, one of the following (listed with the
 *      UTC offsets and comments):
 *          AST -0400   Atlantic Standard Time
 *          ADT -0300   Atlantic Daylight Time
 *          EST -0500   Eastern Standard Time
 *          EDT -0400   Eastern Daylight Time
 *          CST -0600   Central Standard Time
 *          CDT -0500   Central Daylight Time
 *          MST -0700   Mountain Standard Time
 *          MDT -0600   Mountain Daylight Time
 *          PST -0800   Pacific Standard Time
 *          PDT -0700   Pacific Daylight Time
 *          YST -0900   Yukon Standard Time
 *                      (Obsolete, now AKST = Alaska S.T.)
 *          YDT -0800   Yukon Daylight Time
 *                      (Obsolete, now AKDT = Alaska D.T.)
 *          HST -1000   Hawaiian Standard Time
 *                      (Obsolete, now HAST = Hawaiian/Aleutian S.T.)
 *          HDT -0900   Hawaiian Daylight Time
 *                      (Obsolete, now HADT = Hawaiian/Aleutian D.T.)
 *          BST -1100   Used in American Samoa & Midway Island
 *                      (Obsolete, now SST = Samoa S.T.)
 *          BDT -1000   Nonsensical, standard time is used
 *                      all year around in the SST territories.
 * zzzzz is an numeric time zone offset in the form +HHMM
 *      or -HMMM.
 *
 * Returns: Number of characters consumed from @s on success,
 *          or -1 on error.
 */
EXPORTED int time_from_rfc3501(const char *s, time_t *date)
{
    const char *origs = s;
    int c;
    struct tm tm;
    int old_format = 0;
    char month[4], zone[4], *p;
    time_t tmp_gmtime;
    int zone_off;   /* timezone offset in minutes */

    memset(&tm, 0, sizeof tm);

    /* Day of month */
    c = *s++;
    if (c == ' ')
        c = '0';
    else if (!isdigit(c))
        goto baddate;
    tm.tm_mday = c - '0';

    c = *s++;
    if (isdigit(c)) {
        tm.tm_mday = tm.tm_mday * 10 + c - '0';
        c = *s++;
        if (tm.tm_mday <= 0 || tm.tm_mday > 31)
            goto baddate;
    }

    if (c != '-')
        goto baddate;
    c = *s++;

    /* Month name */
    if (!isalpha(c))
        goto baddate;
    month[0] = c;
    c = *s++;
    if (!isalpha(c))
        goto baddate;
    month[1] = c;
    c = *s++;
    if (!isalpha(c))
        goto baddate;
    month[2] = c;
    c = *s++;
    month[3] = '\0';

    for (tm.tm_mon = 0; tm.tm_mon < 12; tm.tm_mon++) {
        if (!strcasecmp(month, monthname[tm.tm_mon]))
            break;
    }
    if (tm.tm_mon == 12)
        goto baddate;

    if (c != '-')
        goto baddate;
    c = *s++;

    /* Year */
    if (!isdigit(c))
        goto baddate;
    tm.tm_year = c - '0';
    c = *s++;
    if (!isdigit(c))
        goto baddate;
    tm.tm_year = tm.tm_year * 10 + c - '0';
    c = *s++;
    if (isdigit(c)) {
        if (tm.tm_year < 19)
            goto baddate;
        tm.tm_year -= 19;
        tm.tm_year = tm.tm_year * 10 + c - '0';
        c = *s++;
        if (!isdigit(c))
            goto baddate;
        tm.tm_year = tm.tm_year * 10 + c - '0';
        c = *s++;
    }
    else
        old_format++;

    if (tm.tm_mday > monthdays(tm.tm_year, tm.tm_mon))
        goto baddate;

    /* Hour */
    if (c != ' ')
        goto baddate;
    c = *s++;
    if (!isdigit(c))
        goto baddate;
    tm.tm_hour = c - '0';
    c = *s++;
    if (!isdigit(c))
        goto baddate;
    tm.tm_hour = tm.tm_hour * 10 + c - '0';
    c = *s++;
    if (tm.tm_hour > 23)
        goto baddate;

    /* Minute */
    if (c != ':')
        goto baddate;
    c = *s++;
    if (!isdigit(c))
        goto baddate;
    tm.tm_min = c - '0';
    c = *s++;
    if (!isdigit(c))
        goto baddate;
    tm.tm_min = tm.tm_min * 10 + c - '0';
    c = *s++;
    if (tm.tm_min > 59)
        goto baddate;

    /* Second */
    if (c != ':')
        goto baddate;
    c = *s++;
    if (!isdigit(c))
        goto baddate;
    tm.tm_sec = c - '0';
    c = *s++;
    if (!isdigit(c))
        goto baddate;
    tm.tm_sec = tm.tm_sec * 10 + c - '0';
    c = *s++;
    if (tm.tm_min > 60)
        goto baddate;

    /* Time zone */
    if (old_format) {
        if (c != '-')
            goto baddate;
        c = *s++;

        if (!isalpha(c))
            goto baddate;
        zone[0] = c;
        c = *s++;

        if (c == '\0') {
            /* Military (single-char) zones */
            zone[1] = '\0';
            lcase(zone);
            if (zone[0] <= 'i') {
                zone_off = (zone[0] - 'a' + 1)*60;
            }
            else if (zone[0] == 'j') {
                goto baddate;
            }
            else if (zone[0] <= 'm') {
                zone_off = (zone[0] - 'k' + 10)*60;
            }
            else if (zone[0] < 'z') {
                zone_off = ('m' - zone[0])*60;
            }
            else    /* 'z' */
                zone_off = 0;
        }
        else {
            /* UT (universal time) */
            zone[1] = c;
            c = *s++;
            if (c == '\0') {
                zone[2] = '\0';
                lcase(zone);
                if (!strcmp(zone, "ut"))
                    goto baddate;
                zone_off = 0;
            }
            else {
                /* 3-char time zone */
                zone[2] = c;
                c = *s++;
                if (c != '\0')
                    goto baddate;
                zone[3] = '\0';
                lcase(zone);
                p = strchr("aecmpyhb", zone[0]);
                if (c != '\0' || zone[2] != 't' || !p)
                    goto baddate;
                zone_off = (strlen(p) - 12)*60;
                if (zone[1] == 'd')
                    zone_off += 60;
                else if (zone[1] != 's')
                    goto baddate;
            }
        }
    }
    else {
        if (c != ' ')
            goto baddate;
        c = *s++;

        if (c != '+' && c != '-')
            goto baddate;
        zone[0] = c;

        c = *s++;
        if (!isdigit(c))
            goto baddate;
        zone_off = c - '0';
        c = *s++;
        if (!isdigit(c))
            goto baddate;
        zone_off = zone_off * 10 + c - '0';
        c = *s++;
        if (!isdigit(c))
            goto baddate;
        zone_off = zone_off * 6 + c - '0';
        c = *s++;
        if (!isdigit(c))
            goto baddate;
        zone_off = zone_off * 10 + c - '0';

        if (zone[0] == '-')
            zone_off = -zone_off;

        c = *s++;
        if (c != '\0')
            goto baddate;
    }

    tm.tm_isdst = -1;

    tmp_gmtime = mkgmtime(&tm);
    if (tmp_gmtime == -1)
        goto baddate;

    *date = tmp_gmtime - zone_off*60;

    return s-1 - origs;

baddate:
    return -1;
}
Exemple #10
0
static int parse_rfc822(const char *s, time_t *tp, int dayonly)
{
    const char *origs = s;
    struct tm tm;
    time_t t;
    char month[4];
    int zone_off = 0;

    if (!s)
        goto baddate;

    memset(&tm, 0, sizeof(tm));

    s = skip_fws(s);
    if (!s)
        goto baddate;

    if (Uisalpha(*s)) {
        /* Day name -- skip over it */
        s++;
        if (!Uisalpha(*s))
            goto baddate;
        s++;
        if (!Uisalpha(*s))
            goto baddate;
        s++;
        s = skip_fws(s);
        if (!s || *s++ != ',')
            goto baddate;
        s = skip_fws(s);
        if (!s)
            goto baddate;
    }

    if (!Uisdigit(*s))
        goto baddate;
    tm.tm_mday = *s++ - '0';
    if (Uisdigit(*s)) {
        tm.tm_mday = tm.tm_mday*10 + *s++ - '0';
    }

    /* Parse month name */
    s = skip_fws(s);
    if (!s)
        goto baddate;
    month[0] = *s++;
    if (!Uisalpha(month[0]))
        goto baddate;
    month[1] = *s++;
    if (!Uisalpha(month[1]))
        goto baddate;
    month[2] = *s++;
    if (!Uisalpha(month[2]))
        goto baddate;
    month[3] = '\0';
    for (tm.tm_mon = 0; tm.tm_mon < 12; tm.tm_mon++) {
        if (!strcasecmp(month, monthname[tm.tm_mon])) break;
    }
    if (tm.tm_mon == 12)
        goto baddate;

    /* Parse year */
    s = skip_fws(s);
    if (!s || !Uisdigit(*s))
        goto baddate;
    tm.tm_year = *s++ - '0';
    if (!Uisdigit(*s))
        goto baddate;
    tm.tm_year = tm.tm_year * 10 + *s++ - '0';
    if (Uisdigit(*s)) {
        if (tm.tm_year < 19)
            goto baddate;
        tm.tm_year -= 19;
        tm.tm_year = tm.tm_year * 10 + *s++ - '0';
        if (!Uisdigit(*s))
            goto baddate;
        tm.tm_year = tm.tm_year * 10 + *s++ - '0';
    } else {
        if (tm.tm_year < 70) {
            /* two-digit year, probably after 2000.
             * This patent was overturned, right?
             */
            tm.tm_year += 100;
        }
    }
    if (Uisdigit(*s)) {
       /* five-digit date */
       goto baddate;
     }

    if (tm.tm_mday > monthdays(tm.tm_year, tm.tm_mon))
        goto baddate;

    s = skip_fws(s);
    if (s && !dayonly) {
        /* Parse hour */
        if (!s || !Uisdigit(*s))
            goto badtime;
        tm.tm_hour = *s++ - '0';
        if (!Uisdigit(*s))
            goto badtime;
        tm.tm_hour = tm.tm_hour * 10 + *s++ - '0';
        if (!s || *s++ != ':')
            goto badtime;

        /* Parse min */
        if (!s || !Uisdigit(*s))
            goto badtime;
        tm.tm_min = *s++ - '0';
        if (!Uisdigit(*s))
            goto badtime;
        tm.tm_min = tm.tm_min * 10 + *s++ - '0';

        if (*s == ':') {
            /* Parse sec */
            if (!++s || !Uisdigit(*s))
                goto badtime;
            tm.tm_sec = *s++ - '0';
            if (!Uisdigit(*s))
                goto badtime;
            tm.tm_sec = tm.tm_sec * 10 + *s++ - '0';
        }

        s = skip_fws(s);
        if (s) {
            /* Parse timezone offset */
            if (*s == '+' || *s == '-') {
                /* Parse numeric offset */
                int east = (*s++ == '-');

                if (!s || !Uisdigit(*s))
                    goto badzone;
                zone_off = *s++ - '0';
                if (!s || !Uisdigit(*s))
                    goto badzone;
                zone_off = zone_off * 10 + *s++ - '0';
                if (!s || !Uisdigit(*s))
                    goto badzone;
                zone_off = zone_off * 6 + *s++ - '0';
                if (!s || !Uisdigit(*s))
                    goto badzone;
                zone_off = zone_off * 10 + *s++ - '0';

                if (east)
                    zone_off = -zone_off;
            }
            else if (Uisalpha(*s)) {
                char zone[4];

                zone[0] = *s++;
                if (!Uisalpha(*s)) {
                    /* Parse military (single-char) zone */
                    zone[1] = '\0';
                    lcase(zone);
                    if (zone[0] < 'j')
                        zone_off = (zone[0] - 'a' + 1) * 60;
                    else if (zone[0] == 'j')
                        goto badzone;
                    else if (zone[0] <= 'm')
                        zone_off = (zone[0] - 'a') * 60;
                    else if (zone[0] < 'z')
                        zone_off = ('m' - zone[0]) * 60;
                    else
                        zone_off = 0;
                }
                else {
                    zone[1] = *s++;
                    if (!Uisalpha(*s)) {
                        /* Parse UT (universal time) */
                        zone[2] = '\0';
                        lcase(zone);
                        if (strcmp(zone, "ut"))
                            goto badzone;
                        zone_off = 0;
                    }
                    else {
                        /* Parse 3-char time zone */
                        char *p;

                        zone[2] = *s;
                        zone[3] = '\0';
                        lcase(zone);
                        /* GMT (Greenwich mean time) */
                        if (!strcmp(zone, "gmt"))
                            zone_off = 0;

                        /* US time zone */
                        else {
                            p = strchr("aecmpyhb", zone[0]);
                            if (!p || zone[2] != 't')
                                goto badzone;
                            zone_off = (strlen(p) - 12) * 60;
                            if (zone[1] == 'd')
                                zone_off += 60;
                            else if (zone[1] != 's')
                                goto badzone;
                        }
                    }
                }
            }
            else
 badzone:
                zone_off = 0;
        }
    }
    else
 badtime:
        tm.tm_hour = 12;

    tm.tm_isdst = -1;

    if (!dayonly)
        t = mkgmtime(&tm);
    else {
        assert(zone_off == 0);
        t = mktime(&tm);
    }
    if (t >= 0) {
        *tp = (t - zone_off * 60);
        return s - origs;
    }

 baddate:
    return -1;
}