diff --git a/cpp/src/arrow/util/value_parsing_test.cc b/cpp/src/arrow/util/value_parsing_test.cc index b61f777685b7..6eb387fc0319 100644 --- a/cpp/src/arrow/util/value_parsing_test.cc +++ b/cpp/src/arrow/util/value_parsing_test.cc @@ -876,6 +876,38 @@ TEST(TimestampParser, StrptimeParser) { } } +TEST(TimestampParser, StrptimeLocaleDirectives) { + // Directives that use the names and formats of the C locale + struct Case { + std::string format; + std::string value; + std::string iso8601; + }; + + std::vector cases = { + {"%a %d %b %Y", "Sun 15 Feb 2015", "2015-02-15 00:00:00"}, + {"%A %d %B %Y", "Sunday 15 February 2015", "2015-02-15 00:00:00"}, + {"%d %h %Y", "15 Feb 2015", "2015-02-15 00:00:00"}, + {"%d-%b-%Y", "15-feb-2015", "2015-02-15 00:00:00"}, + {"%c", "Sun Feb 15 14:30:00 2015", "2015-02-15 14:30:00"}, + {"%m/%d/%Y %I:%M %p", "02/15/2015 02:30 PM", "2015-02-15 14:30:00"}, + {"%Y-%m-%d %r", "2015-02-15 02:30:00 PM", "2015-02-15 14:30:00"}, + {"%x", "02/15/15", "2015-02-15 00:00:00"}, + {"%Y-%m-%d %X", "2015-02-15 14:30:00", "2015-02-15 14:30:00"}, + }; + + for (const auto& case_ : cases) { + SCOPED_TRACE(case_.format); + auto parser = TimestampParser::MakeStrptime(case_.format); + int64_t converted, expected; + ASSERT_TRUE( + (*parser)(case_.value.c_str(), case_.value.size(), TimeUnit::SECOND, &converted)); + ASSERT_TRUE(ParseTimestampISO8601(case_.iso8601.c_str(), case_.iso8601.size(), + TimeUnit::SECOND, &expected)); + ASSERT_EQ(expected, converted); + } +} + TEST(TimestampParser, StrptimeZoneOffset) { if (!kStrptimeSupportsZone) { GTEST_SKIP() << "strptime does not support %z on this platform"; diff --git a/cpp/src/arrow/vendored/musl/strptime.c b/cpp/src/arrow/vendored/musl/strptime.c index 41912fd1bbf4..eb325108b8a8 100644 --- a/cpp/src/arrow/vendored/musl/strptime.c +++ b/cpp/src/arrow/vendored/musl/strptime.c @@ -23,6 +23,25 @@ #ifdef HAVE_LANGINFO #include +#else +// C-locale replacement for nl_langinfo(), restricted to the items used below. +// The values are those of the POSIX locale (LC_TIME in POSIX.1, chapter 7), +// as in musl's own C locale (c_time in src/locale/langinfo.c), and in the +// same order, which the symbolic_range loop relies on: full names directly +// follow the abbreviated ones. +enum { ABDAY_1 = 0, DAY_1 = 7, ABMON_1 = 14, MON_1 = 26, AM_STR = 38, PM_STR = 39, + D_T_FMT = 40, D_FMT = 41, T_FMT = 42, T_FMT_AMPM = 43 }; +static const char *arrow_c_langinfo[] = { + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", + "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", + "January", "February", "March", "April", "May", "June", + "July", "August", "September", "October", "November", "December", + "AM", "PM", + "%a %b %e %T %Y", "%m/%d/%y", "%H:%M:%S", "%I:%M:%S %p"}; +#define nl_langinfo(x) arrow_c_langinfo[x] +#define HAVE_LANGINFO 1 #endif #define strptime arrow_strptime diff --git a/r/tests/testthat/test-dplyr-funcs-datetime.R b/r/tests/testthat/test-dplyr-funcs-datetime.R index db036bcdea11..2f99b6d75026 100644 --- a/r/tests/testthat/test-dplyr-funcs-datetime.R +++ b/r/tests/testthat/test-dplyr-funcs-datetime.R @@ -238,8 +238,6 @@ test_that("strptime works for individual formats", { collect() ) - # Some formats are not supported on Windows - skip_on_os("windows") expect_equal( strptime_test_df |> arrow_table() |>