common: Add new function isodate_human_to_tm

* common/gettime.c (isotime_human_p): Add arg date_only.
(isodate_human_to_tm): New.
* common/t-gettime.c (test_isodate_human_to_tm): New.
(main): Call new test.
--

This function in intended as replacement for

 strptime (foo, "%Y-%m-%d", &bar)

which is not available under Windows.
This commit is contained in:
Werner Koch 2015-04-10 12:02:31 +02:00
parent 6ad95fe6f1
commit f6670100b7
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
3 changed files with 114 additions and 4 deletions

View File

@ -216,9 +216,11 @@ isotime_p (const char *string)
/* Scan a string and return true if the string represents the human
readable format of an ISO time. This format is:
yyyy-mm-dd[ hh[:mm[:ss]]]
Scanning stops at the second space or at a comma. */
Scanning stops at the second space or at a comma. If DATE_ONLY is
true the time part is not expected and the scanning stops at the
first space or at a comma. */
int
isotime_human_p (const char *string)
isotime_human_p (const char *string, int date_only)
{
const char *s;
int i;
@ -247,6 +249,8 @@ isotime_human_p (const char *string)
return 1; /* Okay; only date given. */
if (!spacep (s))
return 0;
if (date_only)
return 1; /* Okay; only date was requested. */
s++;
if (spacep (s))
return 1; /* Okay, second space stops scanning. */
@ -303,7 +307,7 @@ string2isotime (gnupg_isotime_t atime, const char *string)
atime[15] = 0;
return 15;
}
if (!isotime_human_p (string))
if (!isotime_human_p (string, 0))
return 0;
atime[0] = string[0];
atime[1] = string[1];
@ -393,6 +397,36 @@ epoch2isotime (gnupg_isotime_t timebuf, time_t atime)
}
/* Parse a short ISO date string (YYYY-MM-DD) into a TM structure.
Returns 0 on success. */
int
isodate_human_to_tm (const char *string, struct tm *t)
{
int year, month, day;
if (!isotime_human_p (string, 1))
return -1;
year = atoi_4 (string);
month = atoi_2 (string + 5);
day = atoi_2 (string + 8);
/* Basic checks. */
if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31)
return -1;
memset (t, 0, sizeof *t);
t->tm_sec = 0;
t->tm_min = 0;
t->tm_hour = 0;
t->tm_mday = day;
t->tm_mon = month-1;
t->tm_year = year - 1900;
t->tm_isdst = -1;
return 0;
}
/* This function is a copy of gpgme/src/conversion.c:_gpgme_timegm.
If you change it, then update the other one too. */
#ifdef HAVE_W32_SYSTEM

View File

@ -37,10 +37,11 @@ char *elapsed_time_string (time_t since, time_t now);
u32 scan_isodatestr (const char *string);
int isotime_p (const char *string);
int isotime_human_p (const char *string);
int isotime_human_p (const char *string, int date_only);
size_t string2isotime (gnupg_isotime_t atime, const char *string);
time_t isotime2epoch (const char *string);
void epoch2isotime (gnupg_isotime_t timebuf, time_t atime);
int isodate_human_to_tm (const char *string, struct tm *t);
time_t parse_timestamp (const char *timestamp, char **endp);
u32 add_days_to_timestamp (u32 stamp, u16 days);
const char *strtimevalue (u32 stamp);

View File

@ -174,6 +174,80 @@ test_string2isotime (void)
}
static void
test_isodate_human_to_tm (void)
{
struct {
const char *string;
int okay;
int year, mon, mday;
} array [] = {
{ "1970-01-01", 1, 1970, 1, 1 },
{ "1970-02-01", 1, 1970, 2, 1 },
{ "1970-12-31", 1, 1970, 12, 31 },
{ "1971-01-01", 1, 1971, 1, 1 },
{ "1998-08-15", 1, 1998, 8, 15 },
{ "2015-04-10", 1, 2015, 4, 10 },
{ "2015-04-10 11:30",1, 2015, 4, 10 },
{ "1969-12-31", 0, 0, 0, 0 },
{ "1900-01-01", 0, 0, 0, 0 },
{ "", 0, 0, 0, 0 },
{ "1970-12-32", 0, 0, 0, 0 },
{ "1970-13-01", 0, 0, 0, 0 },
{ "1970-01-00", 0, 0, 0, 0 },
{ "1970-00-01", 0, 0, 0, 0 },
{ "1970-00-01", 0, 0, 0, 0 },
{ "1970", 0, 0, 0, 0 },
{ "1970-01", 0, 0, 0, 0 },
{ "1970-01-1", 0, 0, 0, 0 },
{ "1970-1--01", 0, 0, 0, 0 },
{ "1970-01-01,", 1, 1970, 1, 1 },
{ "1970-01-01 ", 1, 1970, 1, 1 },
{ "1970-01-01\t", 1, 1970, 1, 1 },
{ "1970-01-01;", 0, 0, 0, 0 },
{ "1970-01-01:", 0, 0, 0, 0 },
{ "1970_01-01", 0, 0, 0, 0 },
{ "1970-01_01", 0, 0, 0, 0 },
{ NULL, 0 }
};
int idx;
int okay;
struct tm tmbuf;
for (idx=0; array[idx].string; idx++)
{
okay = !isodate_human_to_tm (array[idx].string, &tmbuf);
if (okay != array[idx].okay)
{
fail (idx);
if (verbose)
fprintf (stderr, "string '%s' expected: %d, got: %d\n",
array[idx].string, (int)array[idx].okay, okay);
}
else if (!okay)
;
else if (tmbuf.tm_year + 1900 != array[idx].year
|| tmbuf.tm_mon +1 != array[idx].mon
|| tmbuf.tm_mday != array[idx].mday)
{
fail (idx);
if (verbose)
fprintf (stderr, "string '%s' returned %04d-%02d-%02d\n",
array[idx].string,
tmbuf.tm_year + 1900, tmbuf.tm_mon + 1, tmbuf.tm_mday);
}
else if (tmbuf.tm_sec || tmbuf.tm_min || tmbuf.tm_hour
|| tmbuf.tm_isdst != -1)
{
fail (idx);
if (verbose)
fprintf (stderr, "string '%s' returned bad time part\n",
array[idx].string);
}
}
}
int
main (int argc, char **argv)
{
@ -182,6 +256,7 @@ main (int argc, char **argv)
test_isotime2epoch ();
test_string2isotime ();
test_isodate_human_to_tm ();
return !!errcount;
}