Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
gh-123681: Check the strftime() behavior at runtime instead of at the…
… compile time

It is needed to support cross-compiling.
Remove macros Py_NORMALIZE_CENTURY and Py_STRFTIME_C99_SUPPORT.
  • Loading branch information
serhiy-storchaka committed Jan 3, 2025
commit 0d17190cc821ee5ce1c1bf6ddafaeeebb2c3f463
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Check the ``strftime()`` behavior at runtime instead of at the compile time
to support cross-compiling. Remove macros Py_NORMALIZE_CENTURY and
Py_STRFTIME_C99_SUPPORT.
50 changes: 39 additions & 11 deletions Modules/_datetimemodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -1740,6 +1740,42 @@ format_utcoffset(char *buf, size_t buflen, const char *sep,
return 0;
}

/* Check whether year with century should be normalized for strftime. */
inline static int
normalize_century(void)
{
static int _normalize_century = -1;
if (_normalize_century < 0) {
char year[5];
struct tm date = {
.tm_year = -1801,
.tm_mon = 0,
.tm_mday = 1
};
_normalize_century = (strftime(year, sizeof(year), "%Y", &date) &&
strcmp(year, "0099") != 0);
}
return _normalize_century;
}

/* Check whether C99-specific strftime specifiers are supported. */
inline static int
strftime_c99_support(void)
{
static int _strftime_c99_support = -1;
if (_strftime_c99_support < 0) {
char full_date[11];
struct tm date = {
.tm_year = 0,
.tm_mon = 0,
.tm_mday = 1
};
_strftime_c99_support = (strftime(full_date, sizeof(full_date), "%F", &date) &&
strcmp(full_date, "1900-01-01") == 0);
}
return _strftime_c99_support;
}

static PyObject *
make_somezreplacement(PyObject *object, char *sep, PyObject *tzinfoarg)
{
Expand Down Expand Up @@ -1910,12 +1946,9 @@ wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple,
}
replacement = freplacement;
}
#ifdef Py_NORMALIZE_CENTURY
else if (ch == 'Y' || ch == 'G'
#ifdef Py_STRFTIME_C99_SUPPORT
|| ch == 'F' || ch == 'C'
#endif
) {
else if (normalize_century() && (ch == 'Y' || ch == 'G' ||
(strftime_c99_support() && (ch == 'F' || ch == 'C'))))
{
/* 0-pad year with century as necessary */
PyObject *item = PySequence_GetItem(timetuple, 0);
if (item == NULL) {
Expand Down Expand Up @@ -1952,15 +1985,11 @@ wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple,
* +6 to accommodate dashes, 2-digit month and day for %F. */
char buf[SIZEOF_LONG * 5 / 2 + 2 + 6];
Py_ssize_t n = PyOS_snprintf(buf, sizeof(buf),
#ifdef Py_STRFTIME_C99_SUPPORT
ch == 'F' ? "%04ld-%%m-%%d" :
#endif
"%04ld", year_long);
#ifdef Py_STRFTIME_C99_SUPPORT
if (ch == 'C') {
n -= 2;
}
#endif
if (_PyUnicodeWriter_WriteSubstring(&writer, format, start, end) < 0) {
goto Error;
}
Expand All @@ -1970,7 +1999,6 @@ wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple,
}
continue;
}
#endif
else {
/* percent followed by something else */
continue;
Expand Down
104 changes: 0 additions & 104 deletions configure

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

56 changes: 0 additions & 56 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -6644,62 +6644,6 @@ then
[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-specific 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_cv_strftime_c99_support=no],
[ac_cv_strftime_c99_support=no])])
if test "$ac_cv_strftime_c99_support" = yes
then
AC_DEFINE([Py_STRFTIME_C99_SUPPORT], [1],
[Define if C99-specific strftime specifiers are supported.])
fi

dnl check for ncursesw/ncurses and panelw/panel
dnl NOTE: old curses is not detected.
dnl have_curses=[no, yes]
Expand Down
6 changes: 0 additions & 6 deletions pyconfig.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -1706,18 +1706,12 @@
/* Defined if _Complex C type is available. */
#undef Py_HAVE_C_COMPLEX

/* Define if year with century should be normalized for strftime. */
#undef Py_NORMALIZE_CENTURY

/* Define if rl_startup_hook takes arguments */
#undef Py_RL_STARTUP_HOOK_TAKES_ARGS

/* Define if you want to enable internal statistics gathering. */
#undef Py_STATS

/* Define if C99-specific strftime specifiers are supported. */
#undef Py_STRFTIME_C99_SUPPORT

/* The version of SunOS/Solaris as reported by `uname -r' without the dot. */
#undef Py_SUNOS_VERSION

Expand Down