From 588abe53669600c327e7dfa0a6343f823ae98b12 Mon Sep 17 00:00:00 2001 From: Tadeja Kadunc Date: Fri, 6 Nov 2026 22:49:27 +0100 Subject: [PATCH 1/4] Truncate to seconds --- cpp/src/arrow/filesystem/s3fs.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cpp/src/arrow/filesystem/s3fs.cc b/cpp/src/arrow/filesystem/s3fs.cc index 76b1ce616143..dee693bed96a 100644 --- a/cpp/src/arrow/filesystem/s3fs.cc +++ b/cpp/src/arrow/filesystem/s3fs.cc @@ -2247,7 +2247,11 @@ void FileObjectToInfo(std::string_view key, const S3Model::HeadObjectResult& obj void FileObjectToInfo(const S3Model::Object& obj, FileInfo* info) { info->set_type(FileType::File); info->set_size(static_cast(obj.GetSize())); - info->set_mtime(FromAwsDatetime(obj.GetLastModified())); + // AWS SDK version >=1.11.900 keeps milliseconds in ListObjectsV2. + // HeadObject's Last-Modified header has only seconds. Truncate so mtime + // doesn't depend on what returns it + info->set_mtime( + std::chrono::floor(FromAwsDatetime(obj.GetLastModified()))); } } // namespace From 402fe02e99a85b9e2bfc234773937250246bc2a4 Mon Sep 17 00:00:00 2001 From: Tadeja Kadunc Date: Sat, 7 Nov 2026 00:02:52 +0100 Subject: [PATCH 2/4] Revert "Truncate to seconds" This reverts commit 588abe53669600c327e7dfa0a6343f823ae98b12. --- cpp/src/arrow/filesystem/s3fs.cc | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/cpp/src/arrow/filesystem/s3fs.cc b/cpp/src/arrow/filesystem/s3fs.cc index dee693bed96a..76b1ce616143 100644 --- a/cpp/src/arrow/filesystem/s3fs.cc +++ b/cpp/src/arrow/filesystem/s3fs.cc @@ -2247,11 +2247,7 @@ void FileObjectToInfo(std::string_view key, const S3Model::HeadObjectResult& obj void FileObjectToInfo(const S3Model::Object& obj, FileInfo* info) { info->set_type(FileType::File); info->set_size(static_cast(obj.GetSize())); - // AWS SDK version >=1.11.900 keeps milliseconds in ListObjectsV2. - // HeadObject's Last-Modified header has only seconds. Truncate so mtime - // doesn't depend on what returns it - info->set_mtime( - std::chrono::floor(FromAwsDatetime(obj.GetLastModified()))); + info->set_mtime(FromAwsDatetime(obj.GetLastModified())); } } // namespace From 5a529fdb2b49bbf2604f4e813c3ed1e658c84a57 Mon Sep 17 00:00:00 2001 From: Tadeja Kadunc Date: Sat, 7 Nov 2026 00:04:59 +0100 Subject: [PATCH 3/4] Compare mtimes at seconds in test instead of truncate --- cpp/src/arrow/filesystem/test_util.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cpp/src/arrow/filesystem/test_util.cc b/cpp/src/arrow/filesystem/test_util.cc index da73a8ec16b5..b1ce0ba80a39 100644 --- a/cpp/src/arrow/filesystem/test_util.cc +++ b/cpp/src/arrow/filesystem/test_util.cc @@ -811,7 +811,11 @@ void GenericFileSystemTest::TestGetFileInfoSelector(FileSystem* fs) { ASSERT_OK_AND_ASSIGN(info, fs->GetFileInfo("AB")); AssertFileInfo(info, "AB", FileType::Directory, first_dir_time); ASSERT_OK_AND_ASSIGN(info, fs->GetFileInfo("AB/CD/ghi")); - AssertFileInfo(info, "AB/CD/ghi", FileType::File, first_file_time, 15); + AssertFileInfo(info, "AB/CD/ghi", FileType::File, 15); + // A single-file call may return a less precise mtime than a selector call, + // so compare seconds (e.g. S3 Last-Modified header only has seconds) + ASSERT_EQ(std::chrono::floor(info.mtime()), + std::chrono::floor(first_file_time)); // Doesn't exist s.base_dir = "XX"; From cf03b363121bbeb238fd111bd0d51428300527ef Mon Sep 17 00:00:00 2001 From: tadeja Date: Sat, 7 Nov 2026 15:04:26 +0100 Subject: [PATCH 4/4] Update cpp/src/arrow/filesystem/test_util.cc Co-authored-by: Rok Mihevc --- cpp/src/arrow/filesystem/test_util.cc | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/cpp/src/arrow/filesystem/test_util.cc b/cpp/src/arrow/filesystem/test_util.cc index b1ce0ba80a39..1b96e485fdf9 100644 --- a/cpp/src/arrow/filesystem/test_util.cc +++ b/cpp/src/arrow/filesystem/test_util.cc @@ -811,11 +811,12 @@ void GenericFileSystemTest::TestGetFileInfoSelector(FileSystem* fs) { ASSERT_OK_AND_ASSIGN(info, fs->GetFileInfo("AB")); AssertFileInfo(info, "AB", FileType::Directory, first_dir_time); ASSERT_OK_AND_ASSIGN(info, fs->GetFileInfo("AB/CD/ghi")); - AssertFileInfo(info, "AB/CD/ghi", FileType::File, 15); - // A single-file call may return a less precise mtime than a selector call, - // so compare seconds (e.g. S3 Last-Modified header only has seconds) - ASSERT_EQ(std::chrono::floor(info.mtime()), - std::chrono::floor(first_file_time)); + // aws-sdk-cpp >= 1.11.900 keeps ms in S3 listings, but HeadObject only has seconds + if (info.mtime() == std::chrono::floor(info.mtime()) && + first_file_time == std::chrono::floor(first_file_time)) { + first_file_time = std::chrono::floor(first_file_time); + } + AssertFileInfo(info, "AB/CD/ghi", FileType::File, first_file_time, 15); // Doesn't exist s.base_dir = "XX";