[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