_normalize_century = True
return _normalize_century
-_supports_c99 = None
-def _can_support_c99():
- global _supports_c99
- if _supports_c99 is None:
- try:
- _supports_c99 = (
- _time.strftime("%F", (1900, 1, 1, 0, 0, 0, 0, 1, 0)) == "1900-01-01")
- except ValueError:
- _supports_c99 = False
- return _supports_c99
-
# Correctly substitute for %z and %Z escapes in strftime formats.
def _wrap_strftime(object, format, timetuple):
# Don't call utcoffset() or tzname() unless actually needed.
newformat.append(Zreplace)
# Note that datetime(1000, 1, 1).strftime('%G') == '1000' so
# year 1000 for %G can go on the fast path.
- elif ((ch in 'YG' or ch in 'FC' and _can_support_c99()) and
+ elif ((ch in 'YG' or ch in 'FC') and
object.year < 1000 and _need_normalize_century()):
if ch == 'G':
year = int(_time.strftime("%G", timetuple))
self.assertTrue(self.theclass.min)
self.assertTrue(self.theclass.max)
- def test_strftime_y2k(self):
+ def check_strftime_y2k(self, specifier):
# Test that years less than 1000 are 0-padded; note that the beginning
# of an ISO 8601 year may fall in an ISO week of the year before, and
# therefore needs an offset of -1 when formatting with '%G'.
(1000, 0),
(1970, 0),
)
- specifiers = 'YG'
- if _time.strftime('%F', (1900, 1, 1, 0, 0, 0, 0, 1, 0)) == '1900-01-01':
- specifiers += 'FC'
for year, g_offset in dataset:
- for specifier in specifiers:
- with self.subTest(year=year, specifier=specifier):
- d = self.theclass(year, 1, 1)
- if specifier == 'G':
- year += g_offset
- if specifier == 'C':
- expected = f"{year // 100:02d}"
- else:
- expected = f"{year:04d}"
- if specifier == 'F':
- expected += f"-01-01"
- self.assertEqual(d.strftime(f"%{specifier}"), expected)
+ with self.subTest(year=year, specifier=specifier):
+ d = self.theclass(year, 1, 1)
+ if specifier == 'G':
+ year += g_offset
+ if specifier == 'C':
+ expected = f"{year // 100:02d}"
+ else:
+ expected = f"{year:04d}"
+ if specifier == 'F':
+ expected += f"-01-01"
+ self.assertEqual(d.strftime(f"%{specifier}"), expected)
+
+ def test_strftime_y2k(self):
+ self.check_strftime_y2k('Y')
+ self.check_strftime_y2k('G')
+
+ def test_strftime_y2k_c99(self):
+ # CPython requires C11; specifiers new in C99 must work.
+ # (Other implementations may want to disable this test.)
+ self.check_strftime_y2k('F')
+ self.check_strftime_y2k('C')
def test_replace(self):
cls = self.theclass
--- /dev/null
+Check the ``strftime()`` behavior at runtime instead of at the compile time
+to support cross-compiling.
+Remove the internal macro ``_Py_NORMALIZE_CENTURY``.
return 0;
}
+/* Check whether year with century should be normalized for strftime. */
+inline static int
+normalize_century(void)
+{
+ static int cache = -1;
+ if (cache < 0) {
+ char year[5];
+ struct tm date = {
+ .tm_year = -1801,
+ .tm_mon = 0,
+ .tm_mday = 1
+ };
+ cache = (strftime(year, sizeof(year), "%Y", &date) &&
+ strcmp(year, "0099") != 0);
+ }
+ return cache;
+}
+
static PyObject *
make_somezreplacement(PyObject *object, char *sep, PyObject *tzinfoarg)
{
}
replacement = freplacement;
}
-#ifdef _Py_NORMALIZE_CENTURY
- else if (ch == 'Y' || ch == 'G'
- || ch == 'F' || ch == 'C'
- ) {
+ else if (normalize_century()
+ && (ch == 'Y' || ch == 'G' || ch == 'F' || ch == 'C'))
+ {
/* 0-pad year with century as necessary */
PyObject *item = PySequence_GetItem(timetuple, 0);
if (item == NULL) {
}
continue;
}
-#endif
else {
/* percent followed by something else */
continue;
Modules/_datetimemodule.c parse_hh_mm_ss_ff correction -
Modules/_datetimemodule.c time_isoformat specs -
Modules/_datetimemodule.c - capi_types -
+Modules/_datetimemodule.c normalize_century cache -
Modules/_decimal/_decimal.c - cond_map_template -
Modules/_decimal/_decimal.c - dec_signal_string -
Modules/_decimal/_decimal.c - dflt_ctx -
fi
-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether year with century should be normalized for strftime" >&5
-printf %s "checking whether year with century should be normalized for strftime... " >&6; }
-if test ${ac_cv_normalize_century+y}
-then :
- printf %s "(cached) " >&6
-else case e in #(
- e)
-if test "$cross_compiling" = yes
-then :
- ac_cv_normalize_century=yes
-else case e in #(
- e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-#include <time.h>
-#include <string.h>
-
-int main(void)
-{
- char year[5];
- struct tm date = {
- .tm_year = -1801,
- .tm_mon = 0,
- .tm_mday = 1
- };
- if (strftime(year, sizeof(year), "%Y", &date) && !strcmp(year, "0099")) {
- return 1;
- }
- return 0;
-}
-
-_ACEOF
-if ac_fn_c_try_run "$LINENO"
-then :
- ac_cv_normalize_century=yes
-else case e in #(
- e) ac_cv_normalize_century=no ;;
-esac
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
- conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
-esac
-fi
- ;;
-esac
-fi
-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_normalize_century" >&5
-printf "%s\n" "$ac_cv_normalize_century" >&6; }
-if test "$ac_cv_normalize_century" = yes
-then
-
-printf "%s\n" "#define _Py_NORMALIZE_CENTURY 1" >>confdefs.h
-
-fi
-
-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether C99-compatible strftime specifiers are supported" >&5
-printf %s "checking whether C99-compatible strftime specifiers are supported... " >&6; }
-if test ${ac_cv_strftime_c99_support+y}
-then :
- printf %s "(cached) " >&6
-else case e in #(
- e)
-if test "$cross_compiling" = yes
-then :
- ac_cv_strftime_c99_support=
-else case e in #(
- e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-#include <time.h>
-#include <string.h>
-
-int main(void)
-{
- char full_date[11];
- struct tm date = {
- .tm_year = 0,
- .tm_mon = 0,
- .tm_mday = 1
- };
- if (strftime(full_date, sizeof(full_date), "%F", &date) && !strcmp(full_date, "1900-01-01")) {
- return 0;
- }
- return 1;
-}
-
-_ACEOF
-if ac_fn_c_try_run "$LINENO"
-then :
- ac_cv_strftime_c99_support=yes
-else case e in #(
- e) as_fn_error $? "Python requires C99-compatible strftime specifiers" "$LINENO" 5 ;;
-esac
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
- conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
-esac
-fi
- ;;
-esac
-fi
-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_strftime_c99_support" >&5
-printf "%s\n" "$ac_cv_strftime_c99_support" >&6; }
-
have_curses=no
have_panel=no
[Define if you have struct stat.st_mtimensec])
fi
-AC_CACHE_CHECK([whether year with century should be normalized for strftime], [ac_cv_normalize_century], [
-AC_RUN_IFELSE([AC_LANG_SOURCE([[
-#include <time.h>
-#include <string.h>
-
-int main(void)
-{
- char year[5];
- struct tm date = {
- .tm_year = -1801,
- .tm_mon = 0,
- .tm_mday = 1
- };
- if (strftime(year, sizeof(year), "%Y", &date) && !strcmp(year, "0099")) {
- return 1;
- }
- return 0;
-}
-]])],
-[ac_cv_normalize_century=yes],
-[ac_cv_normalize_century=no],
-[ac_cv_normalize_century=yes])])
-if test "$ac_cv_normalize_century" = yes
-then
- AC_DEFINE([_Py_NORMALIZE_CENTURY], [1],
- [Define if year with century should be normalized for strftime.])
-fi
-
-AC_CACHE_CHECK([whether C99-compatible strftime specifiers are supported], [ac_cv_strftime_c99_support], [
-AC_RUN_IFELSE([AC_LANG_SOURCE([[
-#include <time.h>
-#include <string.h>
-
-int main(void)
-{
- char full_date[11];
- struct tm date = {
- .tm_year = 0,
- .tm_mon = 0,
- .tm_mday = 1
- };
- if (strftime(full_date, sizeof(full_date), "%F", &date) && !strcmp(full_date, "1900-01-01")) {
- return 0;
- }
- return 1;
-}
-]])],
-[ac_cv_strftime_c99_support=yes],
-[AC_MSG_ERROR([Python requires C99-compatible strftime specifiers])],
-[ac_cv_strftime_c99_support=])])
-
dnl check for ncursesw/ncurses and panelw/panel
dnl NOTE: old curses is not detected.
dnl have_curses=[no, yes]
/* HACL* library can compile SIMD256 implementations */
#undef _Py_HACL_CAN_COMPILE_VEC256
-/* Define if year with century should be normalized for strftime. */
-#undef _Py_NORMALIZE_CENTURY
-
/* Define to force use of thread-safe errno, h_errno, and other functions */
#undef _REENTRANT