Merge "Fix strftime if tm_zone is null."

am: 5780f9d809

* commit '5780f9d80963fbe7b93f501dd3dd7edc7fab46b0':
  Fix strftime if tm_zone is null.
This commit is contained in:
Elliott Hughes 2015-11-13 03:04:31 +00:00 committed by android-build-merger
commit 5187baa387
3 changed files with 58 additions and 1 deletions

View file

@ -725,6 +725,7 @@ LOCAL_CFLAGS := $(libc_common_cflags) \
LOCAL_CFLAGS += -DALL_STATE
# Include tzsetwall, timelocal, timegm, time2posix, and posix2time.
LOCAL_CFLAGS += -DSTD_INSPIRED
# Obviously, we want to be thread-safe.
LOCAL_CFLAGS += -DTHREAD_SAFE
# The name of the tm_gmtoff field in our struct tm.
LOCAL_CFLAGS += -DTM_GMTOFF=tm_gmtoff
@ -732,6 +733,8 @@ LOCAL_CFLAGS += -DTM_GMTOFF=tm_gmtoff
LOCAL_CFLAGS += -DTZDIR=\"/system/usr/share/zoneinfo\"
# Include timezone and daylight globals.
LOCAL_CFLAGS += -DUSG_COMPAT=1
# Use the empty string (instead of " ") as the timezone abbreviation fallback.
LOCAL_CFLAGS += -DWILDABBR=\"\"
LOCAL_CFLAGS += -DNO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU
LOCAL_CFLAGS += -Dlint

View file

@ -502,7 +502,23 @@ label:
continue;
case 'Z':
#ifdef TM_ZONE
pt = _add(t->TM_ZONE, pt, ptlim, modifier);
// BEGIN: Android-changed.
{
const char* zone = t->TM_ZONE;
if (!zone || !*zone) {
// "The value of tm_isdst shall be positive if Daylight Savings Time is
// in effect, 0 if Daylight Savings Time is not in effect, and negative
// if the information is not available."
if (t->tm_isdst == 0) zone = tzname[0];
else if (t->tm_isdst > 0) zone = tzname[1];
// "Replaced by the timezone name or abbreviation, or by no bytes if no
// timezone information exists."
if (!zone || !*zone) zone = "";
}
pt = _add(zone, pt, ptlim, modifier);
}
// END: Android-changed.
#else
if (t->tm_isdst >= 0)
pt = _add(tzname[t->tm_isdst != 0],

View file

@ -143,6 +143,44 @@ TEST(time, strftime) {
EXPECT_STREQ("Sun Mar 10 00:00:00 2100", buf);
}
TEST(time, strftime_null_tm_zone) {
// Netflix on Nexus Player wouldn't start (http://b/25170306).
struct tm t;
memset(&t, 0, sizeof(tm));
char buf[64];
setenv("TZ", "America/Los_Angeles", 1);
tzset();
t.tm_isdst = 0; // "0 if Daylight Savings Time is not in effect".
EXPECT_EQ(5U, strftime(buf, sizeof(buf), "<%Z>", &t));
EXPECT_STREQ("<PST>", buf);
#if defined(__BIONIC__) // glibc 2.19 only copes with tm_isdst being 0 and 1.
t.tm_isdst = 2; // "positive if Daylight Savings Time is in effect"
EXPECT_EQ(5U, strftime(buf, sizeof(buf), "<%Z>", &t));
EXPECT_STREQ("<PDT>", buf);
t.tm_isdst = -123; // "and negative if the information is not available".
EXPECT_EQ(2U, strftime(buf, sizeof(buf), "<%Z>", &t));
EXPECT_STREQ("<>", buf);
#endif
setenv("TZ", "UTC", 1);
tzset();
t.tm_isdst = 0;
EXPECT_EQ(5U, strftime(buf, sizeof(buf), "<%Z>", &t));
EXPECT_STREQ("<UTC>", buf);
#if defined(__BIONIC__) // glibc 2.19 thinks UTC DST is "UTC".
t.tm_isdst = 1; // UTC has no DST.
EXPECT_EQ(2U, strftime(buf, sizeof(buf), "<%Z>", &t));
EXPECT_STREQ("<>", buf);
#endif
}
TEST(time, strptime) {
setenv("TZ", "UTC", 1);