-
Notifications
You must be signed in to change notification settings - Fork 13.6k
[flang] Update the date_and_time intrinsic for AIX #104849
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-flang-runtime Author: Kelvin Li (kkwli) ChangesCurrently, the Full diff: https://github.com/llvm/llvm-project/pull/104849.diff 1 Files Affected:
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) {
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
Ping |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Small style nits. I am not an expert of time intrinsics and cannot test the patch on AIX though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
Thanks for the review. |
Currently, the
strftime
routine is called to get the timezone for theZONE
argument. On AIX, this routine requires an environment variable (i.e.XPG_SUS_ENV=ON
) set in order to return +HHMM/-HHMM with the%z
format. This patch is to add computation of the time difference from UTC for AIX platform.