diff --git a/test/chrono-test.cc b/test/chrono-test.cc
index f986c203847f0..78bf4a60feb2c 100644
--- a/test/chrono-test.cc
+++ b/test/chrono-test.cc
@@ -264,15 +264,15 @@ TEST(chrono_test, system_clock_time_point) {
       "%OU", "%W",  "%OW", "%V",  "%OV", "%j",  "%d",  "%Od", "%e",
       "%Oe", "%a",  "%A",  "%w",  "%Ow", "%u",  "%Ou", "%H",  "%OH",
       "%I",  "%OI", "%M",  "%OM", "%S",  "%OS", "%x",  "%Ex", "%X",
-      "%EX", "%D",  "%F",  "%R",  "%T",  "%p",  "%z",  "%Z"};
+      "%EX", "%D",  "%F",  "%R",  "%T",  "%p"};
 #ifndef _WIN32
   // Disabled on Windows because these formats are not consistent among
   // platforms.
   spec_list.insert(spec_list.end(), {"%c", "%Ec", "%r"});
 #elif defined(__MINGW32__) && !defined(_UCRT)
   // Only C89 conversion specifiers when using MSVCRT instead of UCRT
-  spec_list = {"%%", "%Y", "%y", "%b", "%B", "%m", "%U", "%W", "%j", "%d", "%a",
-               "%A", "%w", "%H", "%I", "%M", "%S", "%x", "%X", "%p", "%Z"};
+  spec_list = {"%%", "%Y", "%y", "%b", "%B", "%m", "%U", "%W", "%j", "%d",
+               "%a", "%A", "%w", "%H", "%I", "%M", "%S", "%x", "%X", "%p"};
 #endif
   spec_list.push_back("%Y-%m-%d %H:%M:%S");
 
@@ -287,19 +287,48 @@ TEST(chrono_test, system_clock_time_point) {
     EXPECT_EQ(sys_output, fmt::format(fmt::runtime(fmt_spec), tm));
   }
 
-  if (std::find(spec_list.cbegin(), spec_list.cend(), "%z") !=
-      spec_list.cend()) {
+#if defined(__MINGW32__) && !defined(_UCRT)
+  spec_list = {"%Z"};
+#else
+  spec_list = {"%z", "%Z"};
+#endif
+  for (const auto& spec : spec_list) {
+    auto t = std::chrono::system_clock::to_time_t(t1);
+    auto tm = *std::localtime(&t);
+
+    auto sys_output = system_strftime(spec, &tm);
+
+    auto fmt_spec = fmt::format("{{:{}}}", spec);
+    EXPECT_EQ(sys_output, fmt::format(fmt::runtime(fmt_spec), tm));
+
+    if (spec == "%z") {
+      sys_output.insert(sys_output.end() - 2, 1, ':');
+      EXPECT_EQ(sys_output, fmt::format("{:%Ez}", tm));
+      EXPECT_EQ(sys_output, fmt::format("{:%Oz}", tm));
+    }
+  }
+
+  if (fmt::detail::has_member_data_tm_zone<std::tm>::value) {
     auto t = std::chrono::system_clock::to_time_t(t1);
     auto tm = *std::gmtime(&t);
 
-    auto sys_output = system_strftime("%z", &tm);
-    sys_output.insert(sys_output.end() - 2, 1, ':');
+    std::vector<std::string> tz_names = {"GMT", "UTC"};
+    EXPECT_THAT(tz_names, Contains(fmt::format("{:%Z}", t1)));
+    EXPECT_THAT(tz_names, Contains(fmt::format("{:%Z}", tm)));
+  }
 
-    EXPECT_EQ(sys_output, fmt::format("{:%Ez}", t1));
-    EXPECT_EQ(sys_output, fmt::format("{:%Ez}", tm));
+  if (fmt::detail::has_member_data_tm_gmtoff<std::tm>::value) {
+    auto t = std::chrono::system_clock::to_time_t(t1);
+    auto tm = *std::gmtime(&t);
 
-    EXPECT_EQ(sys_output, fmt::format("{:%Oz}", t1));
-    EXPECT_EQ(sys_output, fmt::format("{:%Oz}", tm));
+    EXPECT_EQ("+0000", fmt::format("{:%z}", t1));
+    EXPECT_EQ("+0000", fmt::format("{:%z}", tm));
+
+    EXPECT_EQ("+00:00", fmt::format("{:%Ez}", t1));
+    EXPECT_EQ("+00:00", fmt::format("{:%Ez}", tm));
+
+    EXPECT_EQ("+00:00", fmt::format("{:%Oz}", t1));
+    EXPECT_EQ("+00:00", fmt::format("{:%Oz}", tm));
   }
 }
 
diff --git a/test/xchar-test.cc b/test/xchar-test.cc
index f4abbda81ad54..04f2caf5b73e3 100644
--- a/test/xchar-test.cc
+++ b/test/xchar-test.cc
@@ -294,7 +294,7 @@ TEST(chrono_test_wchar, time_point) {
       L"%OU", L"%W",  L"%OW", L"%V",  L"%OV", L"%j",  L"%d",  L"%Od", L"%e",
       L"%Oe", L"%a",  L"%A",  L"%w",  L"%Ow", L"%u",  L"%Ou", L"%H",  L"%OH",
       L"%I",  L"%OI", L"%M",  L"%OM", L"%S",  L"%OS", L"%x",  L"%Ex", L"%X",
-      L"%EX", L"%D",  L"%F",  L"%R",  L"%T",  L"%p",  L"%z",  L"%Z"};
+      L"%EX", L"%D",  L"%F",  L"%R",  L"%T",  L"%p"};
 #ifndef _WIN32
   // Disabled on Windows, because these formats is not consistent among
   // platforms.
@@ -303,7 +303,7 @@ TEST(chrono_test_wchar, time_point) {
   // Only C89 conversion specifiers when using MSVCRT instead of UCRT
   spec_list = {L"%%", L"%Y", L"%y", L"%b", L"%B", L"%m", L"%U",
                L"%W", L"%j", L"%d", L"%a", L"%A", L"%w", L"%H",
-               L"%I", L"%M", L"%S", L"%x", L"%X", L"%p", L"%Z"};
+               L"%I", L"%M", L"%S", L"%x", L"%X", L"%p"};
 #endif
   spec_list.push_back(L"%Y-%m-%d %H:%M:%S");
 
@@ -317,6 +317,50 @@ TEST(chrono_test_wchar, time_point) {
     EXPECT_EQ(sys_output, fmt::format(fmt::runtime(fmt_spec), t1));
     EXPECT_EQ(sys_output, fmt::format(fmt::runtime(fmt_spec), tm));
   }
+
+#if defined(__MINGW32__) && !defined(_UCRT)
+  spec_list = {L"%Z"};
+#else
+  spec_list = {L"%z", L"%Z"};
+#endif
+  for (const auto& spec : spec_list) {
+    auto t = std::chrono::system_clock::to_time_t(t1);
+    auto tm = *std::localtime(&t);
+
+    auto sys_output = system_wcsftime(spec, &tm);
+
+    auto fmt_spec = fmt::format(L"{{:{}}}", spec);
+    EXPECT_EQ(sys_output, fmt::format(fmt::runtime(fmt_spec), tm));
+
+    if (spec == L"%z") {
+      sys_output.insert(sys_output.end() - 2, 1, L':');
+      EXPECT_EQ(sys_output, fmt::format(L"{:%Ez}", tm));
+      EXPECT_EQ(sys_output, fmt::format(L"{:%Oz}", tm));
+    }
+  }
+
+  if (fmt::detail::has_member_data_tm_zone<std::tm>::value) {
+    auto t = std::chrono::system_clock::to_time_t(t1);
+    auto tm = *std::gmtime(&t);
+
+    std::vector<std::wstring> tz_names = {L"GMT", L"UTC"};
+    EXPECT_THAT(tz_names, Contains(fmt::format(L"{:%Z}", t1)));
+    EXPECT_THAT(tz_names, Contains(fmt::format(L"{:%Z}", tm)));
+  }
+
+  if (fmt::detail::has_member_data_tm_gmtoff<std::tm>::value) {
+    auto t = std::chrono::system_clock::to_time_t(t1);
+    auto tm = *std::gmtime(&t);
+
+    EXPECT_EQ(L"+0000", fmt::format(L"{:%z}", t1));
+    EXPECT_EQ(L"+0000", fmt::format(L"{:%z}", tm));
+
+    EXPECT_EQ(L"+00:00", fmt::format(L"{:%Ez}", t1));
+    EXPECT_EQ(L"+00:00", fmt::format(L"{:%Ez}", tm));
+
+    EXPECT_EQ(L"+00:00", fmt::format(L"{:%Oz}", t1));
+    EXPECT_EQ(L"+00:00", fmt::format(L"{:%Oz}", tm));
+  }
 }
 
 TEST(xchar_test, color) {