[flang-commits] [flang] [flang] Update the date_and_time intrinsic for AIX (PR #104849)

Kelvin Li via flang-commits flang-commits at lists.llvm.org
Mon Aug 19 13:47:23 PDT 2024


https://github.com/kkwli updated https://github.com/llvm/llvm-project/pull/104849

>From 8c61a66a3a5d92a5d1a8efb2104ebb5a34b9d97a Mon Sep 17 00:00:00 2001
From: Kelvin Li <kli at ca.ibm.com>
Date: Mon, 19 Aug 2024 11:43:41 -0400
Subject: [PATCH 1/3] [flang] Update the date_and_time intrinsic for AIX

---
 flang/runtime/time-intrinsic.cpp | 63 ++++++++++++++++++++++++++++++--
 1 file changed, 60 insertions(+), 3 deletions(-)

diff --git a/flang/runtime/time-intrinsic.cpp b/flang/runtime/time-intrinsic.cpp
index 92b937bc6f6267..e6c252c85d1668 100644
--- a/flang/runtime/time-intrinsic.cpp
+++ b/flang/runtime/time-intrinsic.cpp
@@ -247,6 +247,58 @@ static void DateAndTimeUnavailable(Fortran::runtime::Terminator &terminator,
 }
 
 #ifndef _WIN32
+#ifdef _AIX
+// Compute the time difference from GMT/UTC to get around the behavior of
+// strfname on AIX that requires setting an environment variable for numeric
+// value for ZONE.
+// The ZONE and the VALUES(4) arguments of the DATE_AND_TIME intrinsic has
+// the resolution to the minute.
+static int computeUTCDiff(const tm &localTime, bool *err) {
+  tm utcTime;
+  const time_t timer{mktime(const_cast<tm *>(&localTime))};
+  if (timer < 0) {
+    *err = true;
+    return 0;
+  }
+
+  // Get the GMT/UTC time
+  if (gmtime_r(&timer, &utcTime) == nullptr) {
+    *err = true;
+    return 0;
+  }
+
+  // Adjust for day difference
+  auto dayDiff{localTime.tm_mday - utcTime.tm_mday};
+  auto localHr{localTime.tm_hour};
+  if (dayDiff > 0) {
+    if (dayDiff == 1)
+      localHr += 24;
+    else
+      utcTime.tm_hour += 24;
+  } else if (dayDiff < 0) {
+    if (dayDiff == -1)
+      utcTime.tm_hour += 24;
+    else
+      localHr += 24;
+  }
+  return (localHr*60 + localTime.tm_min) - (utcTime.tm_hour*60 + utcTime.tm_min);
+}
+#endif
+
+static std::size_t getUTCOffsetToBuffer(char *buffer, const std::size_t &buffSize,
+    tm *localTime) {
+#ifdef _AIX
+  // format: +HHMM or -HHMM
+  bool err{false};
+  auto utcOffset{computeUTCDiff(*localTime, &err)};
+  auto hour{utcOffset/60};
+  auto hrMin{hour*100 + (utcOffset - hour*60)};
+  auto n{sprintf(buffer, "%+05d", hrMin)};
+  return err ? 0 : n + 1;
+#else
+  return std::strftime(buffer, buffSize, "%z", localTime);
+#endif
+}
 
 // SFINAE helper to return the struct tm.tm_gmtoff which is not a POSIX standard
 // field.
@@ -263,8 +315,13 @@ GetGmtOffset(const TM &tm, fallback_implementation) {
   // tm.tm_gmtoff is not available, there may be platform dependent alternatives
   // (such as using timezone from <time.h> when available), but so far just
   // return -HUGE to report that this information is not available.
-  return -std::numeric_limits<Fortran::runtime::CppTypeFor<
-      Fortran::common::TypeCategory::Integer, KIND>>::max();
+  bool err{false};
+  auto diff{computeUTCDiff(tm, &err)};
+  if (err)
+    return -std::numeric_limits<Fortran::runtime::CppTypeFor<
+        Fortran::common::TypeCategory::Integer, KIND>>::max();
+
+  return diff;
 }
 template <typename TM = struct tm> struct GmtOffsetHelper {
   template <int KIND> struct StoreGmtOffset {
@@ -317,7 +374,7 @@ static void GetDateAndTime(Fortran::runtime::Terminator &terminator, char *date,
     // Note: this may leave the buffer empty on many platforms. Classic flang
     // has a much more complex way of doing this (see __io_timezone in classic
     // flang).
-    auto len{std::strftime(buffer, buffSize, "%z", &localTime)};
+    auto len{getUTCOffsetToBuffer(buffer, buffSize, &localTime)};
     copyBufferAndPad(zone, zoneChars, len);
   }
   if (values) {

>From edfc6fc38c32563f2bfcee0e5fe74b26d51c8458 Mon Sep 17 00:00:00 2001
From: Kelvin Li <kli at ca.ibm.com>
Date: Mon, 19 Aug 2024 16:35:00 -0400
Subject: [PATCH 2/3] Fix format

---
 flang/runtime/time-intrinsic.cpp | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/flang/runtime/time-intrinsic.cpp b/flang/runtime/time-intrinsic.cpp
index e6c252c85d1668..ffae3ed1655f7c 100644
--- a/flang/runtime/time-intrinsic.cpp
+++ b/flang/runtime/time-intrinsic.cpp
@@ -281,18 +281,19 @@ static int computeUTCDiff(const tm &localTime, bool *err) {
     else
       localHr += 24;
   }
-  return (localHr*60 + localTime.tm_min) - (utcTime.tm_hour*60 + utcTime.tm_min);
+  return (localHr*60 + localTime.tm_min) -
+      (utcTime.tm_hour*60 + utcTime.tm_min);
 }
 #endif
 
-static std::size_t getUTCOffsetToBuffer(char *buffer, const std::size_t &buffSize,
-    tm *localTime) {
+static std::size_t getUTCOffsetToBuffer(
+    char *buffer, const std::size_t &buffSize, tm *localTime) {
 #ifdef _AIX
   // format: +HHMM or -HHMM
   bool err{false};
   auto utcOffset{computeUTCDiff(*localTime, &err)};
-  auto hour{utcOffset/60};
-  auto hrMin{hour*100 + (utcOffset - hour*60)};
+  auto hour{utcOffset / 60};
+  auto hrMin{hour * 100 + (utcOffset - hour * 60)};
   auto n{sprintf(buffer, "%+05d", hrMin)};
   return err ? 0 : n + 1;
 #else

>From d73c603934ed2a07fa3738bfa69207aa59510fa9 Mon Sep 17 00:00:00 2001
From: Kelvin Li <kli at ca.ibm.com>
Date: Mon, 19 Aug 2024 16:46:36 -0400
Subject: [PATCH 3/3] Fix format

---
 flang/runtime/time-intrinsic.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/flang/runtime/time-intrinsic.cpp b/flang/runtime/time-intrinsic.cpp
index ffae3ed1655f7c..6d3f5aca185c3e 100644
--- a/flang/runtime/time-intrinsic.cpp
+++ b/flang/runtime/time-intrinsic.cpp
@@ -281,8 +281,8 @@ static int computeUTCDiff(const tm &localTime, bool *err) {
     else
       localHr += 24;
   }
-  return (localHr*60 + localTime.tm_min) -
-      (utcTime.tm_hour*60 + utcTime.tm_min);
+  return (localHr * 60 + localTime.tm_min) -
+      (utcTime.tm_hour * 60 + utcTime.tm_min);
 }
 #endif
 



More information about the flang-commits mailing list