Merge "Add strptime %s."

am: e09c90dec1

Change-Id: I58db9138370c86a1f1dad02a589cfd746d0d8d7a
This commit is contained in:
Elliott Hughes 2018-03-01 18:16:18 +00:00 committed by android-build-merger
commit 4d6ae117cb
2 changed files with 75 additions and 3 deletions

View file

@ -38,7 +38,9 @@
//#include <sys/localedef.h>
#include <ctype.h>
#include <errno.h>
#include <locale.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "tzfile.h"
@ -128,7 +130,7 @@ _strptime(const unsigned char *buf, const char *fmt, struct tm *tm, struct centu
fmt++;
continue;
}
if ((c = *fmt++) != '%')
goto literal;
@ -154,7 +156,7 @@ literal:
_LEGAL_ALT(0);
alt_format |= _ALT_O;
goto again;
/*
* "Complex" conversion rules, implemented through recursion.
*/
@ -169,7 +171,7 @@ literal:
if (!(bp = _strptime(bp, "%m/%d/%y", tm, cr)))
return (NULL);
break;
case 'R': /* The time as "%H:%M". */
_LEGAL_ALT(0);
if (!(bp = _strptime(bp, "%H:%M", tm, cr)))
@ -337,6 +339,25 @@ literal:
return (NULL);
break;
case 's':
{
// Android addition, based on FreeBSD's implementation.
int saved_errno = errno;
errno = 0;
const unsigned char* old_bp = bp;
long n = strtol((const char*) bp, (char**) &bp, 10);
time_t t = n;
if (bp == old_bp || errno == ERANGE || ((long) t) != n) {
errno = saved_errno;
return NULL;
}
errno = saved_errno;
if (localtime_r(&t, tm) == NULL) return NULL;
}
break;
case 'U': /* The week of year, beginning on sunday. */
case 'W': /* The week of year, beginning on monday. */
_LEGAL_ALT(_ALT_O);

View file

@ -871,3 +871,54 @@ TEST(time, ctime_r) {
ASSERT_EQ(buf, ctime_r(&t, buf));
ASSERT_STREQ("Thu Jan 1 00:00:00 1970\n", buf);
}
// https://issuetracker.google.com/37128336
TEST(time, strftime_strptime_s) {
char buf[32];
const struct tm tm0 = { .tm_year = 1982-1900, .tm_mon = 0, .tm_mday = 1 };
setenv("TZ", "America/Los_Angeles", 1);
strftime(buf, sizeof(buf), "<%s>", &tm0);
EXPECT_STREQ("<378720000>", buf);
setenv("TZ", "UTC", 1);
strftime(buf, sizeof(buf), "<%s>", &tm0);
EXPECT_STREQ("<378691200>", buf);
struct tm tm;
setenv("TZ", "America/Los_Angeles", 1);
tzset();
memset(&tm, 0xff, sizeof(tm));
char* p = strptime("378720000x", "%s", &tm);
ASSERT_EQ('x', *p);
EXPECT_EQ(0, tm.tm_sec);
EXPECT_EQ(0, tm.tm_min);
EXPECT_EQ(0, tm.tm_hour);
EXPECT_EQ(1, tm.tm_mday);
EXPECT_EQ(0, tm.tm_mon);
EXPECT_EQ(82, tm.tm_year);
EXPECT_EQ(5, tm.tm_wday);
EXPECT_EQ(0, tm.tm_yday);
EXPECT_EQ(0, tm.tm_isdst);
setenv("TZ", "UTC", 1);
tzset();
memset(&tm, 0xff, sizeof(tm));
p = strptime("378691200x", "%s", &tm);
ASSERT_EQ('x', *p);
EXPECT_EQ(0, tm.tm_sec);
EXPECT_EQ(0, tm.tm_min);
EXPECT_EQ(0, tm.tm_hour);
EXPECT_EQ(1, tm.tm_mday);
EXPECT_EQ(0, tm.tm_mon);
EXPECT_EQ(82, tm.tm_year);
EXPECT_EQ(5, tm.tm_wday);
EXPECT_EQ(0, tm.tm_yday);
EXPECT_EQ(0, tm.tm_isdst);
}
TEST(time, strptime_s_nothing) {
struct tm tm;
ASSERT_EQ(nullptr, strptime("x", "%s", &tm));
}