i synced Android's strptime.c with openbsd's recently, getting rid of unnecessary/accidental differences. i'm left with the following, which i thought was interesting (the last one's probably the most interesting, so definitely stick around even if -- as is likely -- you don't care about/actively don't want the first two!)...
comment says it all here for %v: @@ -182,6 +188,12 @@ return (NULL); break; + case 'v': /* Android: the date as "%e-%b-%Y" for strftime() compat; glibc does this too. */ + _LEGAL_ALT(0); + if (!(bp = _strptime(bp, "%e-%b-%Y", tm, 0))) + return (NULL); + break; + case 'X': /* The time, using the locale's format. */ _LEGAL_ALT(_ALT_E); if (!(bp = _strptime(bp, _ctloc(t_fmt), tm, 0))) (full disclosure: although bionic [Android] and glibc both implement this, free- and net- don't, and iOS/macOS don't.) then "different conversion, similar story" (even down to the details of other OSes that do/don't have this) for %P as a synonym for %p: @@ -305,6 +317,7 @@ fields |= FIELD_TM_MON; break; + case 'P': /* Android addition for strftime() compat; glibc does this too. */ case 'p': /* The locale's equivalent of AM/PM. */ _LEGAL_ALT(0); /* AM? */ and now the interesting one... specifically the gmtime_r() vs localtime_r() difference. as you can see from the comment, freebsd uses localtime_r() -- albeit in a complicated way where they use gmtime_r() but set a flag to translate it back! -- and netbsd uses localtime_r() directly. i'm guessing openbsd might be a mistranslation of the freebsd code, missing that freebsd does two translations? glibc is localtime_r() too, fwiw. am i missing something here, or is this indeed an accidental mistranslation of freebsd? (or have _i_ misunderstood freebsd?) (ignore the whole strtol() bit in the hunk --- that's just noise from me papering over Android's 32-bit ABIs having a 32-bit time_t... another 5-10 years and we should be able to remove that! it's really just the gmtime_r() vs localtime_r() bit that's actually interesting.) @@ -340,11 +353,23 @@ break; case 's': /* Seconds since epoch */ { - int64_t i64; - if (!(_conv_num64(&bp, &i64, 0, INT64_MAX))) - return (NULL); - if (!gmtime_r(&i64, tm)) - return (NULL); + // Android change 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); + errno = saved_errno; + time_t t = n; + if (bp == old_bp || errno == ERANGE || + ((long) t) != n) return NULL; + + if (localtime_r(&t, tm) == NULL) return NULL; + fields = 0xffff; /* everything */ } break;