mirror of
https://github.com/openssl/openssl.git
synced 2025-02-05 14:10:53 +08:00
Improve struct tm population
Using Zeller's congruence to fill the day of week field, Also populate the day of year field. Add unit test to cover a number of cases. Reviewed-by: Rich Salz <rsalz@openssl.org> (Merged from https://github.com/openssl/openssl/pull/3999)
This commit is contained in:
parent
3d0f1cb9fd
commit
1a68e5b0d9
@ -31,6 +31,38 @@ static int leap_year(const int year)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Compute the day of the week and the day of the year from the year, month
|
||||||
|
* and day. The day of the year is straightforward, the day of the week uses
|
||||||
|
* a form of Zeller's congruence. For this months start with March and are
|
||||||
|
* numbered 4 through 15.
|
||||||
|
*/
|
||||||
|
static void determine_days(struct tm *tm)
|
||||||
|
{
|
||||||
|
static const int ydays[12] = {
|
||||||
|
0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
|
||||||
|
};
|
||||||
|
int y = tm->tm_year + 1900;
|
||||||
|
int m = tm->tm_mon;
|
||||||
|
int d = tm->tm_mday;
|
||||||
|
int c;
|
||||||
|
|
||||||
|
tm->tm_yday = ydays[m] + d - 1;
|
||||||
|
if (m >= 2) {
|
||||||
|
/* March and onwards can be one day further into the year */
|
||||||
|
tm->tm_yday += leap_year(y);
|
||||||
|
m += 2;
|
||||||
|
} else {
|
||||||
|
/* Treat January and February as part of the previous year */
|
||||||
|
m += 14;
|
||||||
|
y--;
|
||||||
|
}
|
||||||
|
c = y / 100;
|
||||||
|
y %= 100;
|
||||||
|
/* Zeller's congruance */
|
||||||
|
tm->tm_wday = (d + (13 * m) / 5 + y + y / 4 + c / 4 + 5 * c + 6) % 7;
|
||||||
|
}
|
||||||
|
|
||||||
int asn1_time_to_tm(struct tm *tm, const ASN1_TIME *d)
|
int asn1_time_to_tm(struct tm *tm, const ASN1_TIME *d)
|
||||||
{
|
{
|
||||||
static const int min[9] = { 0, 0, 1, 1, 0, 0, 0, 0, 0 };
|
static const int min[9] = { 0, 0, 1, 1, 0, 0, 0, 0, 0 };
|
||||||
@ -127,6 +159,7 @@ int asn1_time_to_tm(struct tm *tm, const ASN1_TIME *d)
|
|||||||
if (n > md)
|
if (n > md)
|
||||||
goto err;
|
goto err;
|
||||||
tmp.tm_mday = n;
|
tmp.tm_mday = n;
|
||||||
|
determine_days(&tmp);
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
tmp.tm_hour = n;
|
tmp.tm_hour = n;
|
||||||
|
@ -55,10 +55,10 @@ an error.
|
|||||||
|
|
||||||
ASN1_TIME_to_tm() converts the time B<s> to the standard B<tm> structure.
|
ASN1_TIME_to_tm() converts the time B<s> to the standard B<tm> structure.
|
||||||
If B<s> is NULL, then the current time is converted. The output time is GMT.
|
If B<s> is NULL, then the current time is converted. The output time is GMT.
|
||||||
The B<tm_sec>, B<tm_min>, B<tm_hour>, B<tm_mday>, B<tm_mon> and B<tm_year>
|
The B<tm_sec>, B<tm_min>, B<tm_hour>, B<tm_mday>, B<tm_wday>, B<tm_yday>,
|
||||||
fields of B<tm> structure are set to proper values, whereas all other fields
|
B<tm_mon> and B<tm_year> fields of B<tm> structure are set to proper values,
|
||||||
are set to 0. If B<tm> is NULL this function performs a format check on B<s>
|
whereas all other fields are set to 0. If B<tm> is NULL this function performs
|
||||||
only.
|
a format check on B<s> only.
|
||||||
|
|
||||||
ASN1_TIME_diff() sets B<*pday> and B<*psec> to the time difference between
|
ASN1_TIME_diff() sets B<*pday> and B<*psec> to the time difference between
|
||||||
B<from> and B<to>. If B<to> represents a time later than B<from> then
|
B<from> and B<to>. If B<to> represents a time later than B<from> then
|
||||||
|
@ -345,9 +345,89 @@ out:
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const struct {
|
||||||
|
int y, m, d;
|
||||||
|
int yd, wd;
|
||||||
|
} day_of_week_tests[] = {
|
||||||
|
/*YYYY MM DD DoY DoW */
|
||||||
|
{ 1900, 1, 1, 0, 1 },
|
||||||
|
{ 1900, 2, 28, 58, 3 },
|
||||||
|
{ 1900, 3, 1, 59, 4 },
|
||||||
|
{ 1900, 12, 31, 364, 1 },
|
||||||
|
{ 1901, 1, 1, 0, 2 },
|
||||||
|
{ 1970, 1, 1, 0, 4 },
|
||||||
|
{ 1999, 1, 10, 9, 0 },
|
||||||
|
{ 1999, 12, 31, 364, 5 },
|
||||||
|
{ 2000, 1, 1, 0, 6 },
|
||||||
|
{ 2000, 2, 28, 58, 1 },
|
||||||
|
{ 2000, 2, 29, 59, 2 },
|
||||||
|
{ 2000, 3, 1, 60, 3 },
|
||||||
|
{ 2000, 12, 31, 365, 0 },
|
||||||
|
{ 2001, 1, 1, 0, 1 },
|
||||||
|
{ 2008, 1, 1, 0, 2 },
|
||||||
|
{ 2008, 2, 28, 58, 4 },
|
||||||
|
{ 2008, 2, 29, 59, 5 },
|
||||||
|
{ 2008, 3, 1, 60, 6 },
|
||||||
|
{ 2008, 12, 31, 365, 3 },
|
||||||
|
{ 2009, 1, 1, 0, 4 },
|
||||||
|
{ 2011, 1, 1, 0, 6 },
|
||||||
|
{ 2011, 2, 28, 58, 1 },
|
||||||
|
{ 2011, 3, 1, 59, 2 },
|
||||||
|
{ 2011, 12, 31, 364, 6 },
|
||||||
|
{ 2012, 1, 1, 0, 0 },
|
||||||
|
{ 2019, 1, 2, 1, 3 },
|
||||||
|
{ 2019, 2, 2, 32, 6 },
|
||||||
|
{ 2019, 3, 2, 60, 6 },
|
||||||
|
{ 2019, 4, 2, 91, 2 },
|
||||||
|
{ 2019, 5, 2, 121, 4 },
|
||||||
|
{ 2019, 6, 2, 152, 0 },
|
||||||
|
{ 2019, 7, 2, 182, 2 },
|
||||||
|
{ 2019, 8, 2, 213, 5 },
|
||||||
|
{ 2019, 9, 2, 244, 1 },
|
||||||
|
{ 2019, 10, 2, 274, 3 },
|
||||||
|
{ 2019, 11, 2, 305, 6 },
|
||||||
|
{ 2019, 12, 2, 335, 1 },
|
||||||
|
{ 2020, 1, 2, 1, 4 },
|
||||||
|
{ 2020, 2, 2, 32, 0 },
|
||||||
|
{ 2020, 3, 2, 61, 1 },
|
||||||
|
{ 2020, 4, 2, 92, 4 },
|
||||||
|
{ 2020, 5, 2, 122, 6 },
|
||||||
|
{ 2020, 6, 2, 153, 2 },
|
||||||
|
{ 2020, 7, 2, 183, 4 },
|
||||||
|
{ 2020, 8, 2, 214, 0 },
|
||||||
|
{ 2020, 9, 2, 245, 3 },
|
||||||
|
{ 2020, 10, 2, 275, 5 },
|
||||||
|
{ 2020, 11, 2, 306, 1 },
|
||||||
|
{ 2020, 12, 2, 336, 3 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static int test_days(int n)
|
||||||
|
{
|
||||||
|
char d[16];
|
||||||
|
ASN1_TIME *a = NULL;
|
||||||
|
struct tm t;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
BIO_snprintf(d, sizeof(d), "%04d%02d%02d050505Z",
|
||||||
|
day_of_week_tests[n].y, day_of_week_tests[n].m,
|
||||||
|
day_of_week_tests[n].d);
|
||||||
|
|
||||||
|
if (!TEST_ptr(a = ASN1_TIME_new()))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
r = TEST_true(ASN1_TIME_set_string(a, d))
|
||||||
|
&& TEST_true(ASN1_TIME_to_tm(a, &t))
|
||||||
|
&& TEST_int_eq(t.tm_yday, day_of_week_tests[n].yd)
|
||||||
|
&& TEST_int_eq(t.tm_wday, day_of_week_tests[n].wd);
|
||||||
|
|
||||||
|
ASN1_TIME_free(a);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
void register_tests()
|
void register_tests()
|
||||||
{
|
{
|
||||||
ADD_TEST(test_x509_cmp_time_current);
|
ADD_TEST(test_x509_cmp_time_current);
|
||||||
ADD_ALL_TESTS(test_x509_cmp_time, OSSL_NELEM(x509_cmp_tests));
|
ADD_ALL_TESTS(test_x509_cmp_time, OSSL_NELEM(x509_cmp_tests));
|
||||||
ADD_ALL_TESTS(test_x509_time, OSSL_NELEM(x509_format_tests));
|
ADD_ALL_TESTS(test_x509_time, OSSL_NELEM(x509_format_tests));
|
||||||
|
ADD_ALL_TESTS(test_days, OSSL_NELEM(day_of_week_tests));
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user