@@ -247,6 +247,61 @@ static void DateAndTimeUnavailable(Fortran::runtime::Terminator &terminator,
247
247
}
248
248
249
249
#ifndef _WIN32
250
+ #ifdef _AIX
251
+ // Compute the time difference from GMT/UTC to get around the behavior of
252
+ // strfname on AIX that requires setting an environment variable for numeric
253
+ // value for ZONE.
254
+ // The ZONE and the VALUES(4) arguments of the DATE_AND_TIME intrinsic has
255
+ // the resolution to the minute.
256
+ static int computeUTCDiff (const tm &localTime, bool *err) {
257
+ tm utcTime;
258
+ const time_t timer{mktime (const_cast <tm *>(&localTime))};
259
+ if (timer < 0 ) {
260
+ *err = true ;
261
+ return 0 ;
262
+ }
263
+
264
+ // Get the GMT/UTC time
265
+ if (gmtime_r (&timer, &utcTime) == nullptr ) {
266
+ *err = true ;
267
+ return 0 ;
268
+ }
269
+
270
+ // Adjust for day difference
271
+ auto dayDiff{localTime.tm_mday - utcTime.tm_mday };
272
+ auto localHr{localTime.tm_hour };
273
+ if (dayDiff > 0 ) {
274
+ if (dayDiff == 1 ) {
275
+ localHr += 24 ;
276
+ } else {
277
+ utcTime.tm_hour += 24 ;
278
+ }
279
+ } else if (dayDiff < 0 ) {
280
+ if (dayDiff == -1 ) {
281
+ utcTime.tm_hour += 24 ;
282
+ } else {
283
+ localHr += 24 ;
284
+ }
285
+ }
286
+ return (localHr * 60 + localTime.tm_min ) -
287
+ (utcTime.tm_hour * 60 + utcTime.tm_min );
288
+ }
289
+ #endif
290
+
291
+ static std::size_t getUTCOffsetToBuffer (
292
+ char *buffer, const std::size_t &buffSize, tm *localTime) {
293
+ #ifdef _AIX
294
+ // format: +HHMM or -HHMM
295
+ bool err{false };
296
+ auto utcOffset{computeUTCDiff (*localTime, &err)};
297
+ auto hour{utcOffset / 60 };
298
+ auto hrMin{hour * 100 + (utcOffset - hour * 60 )};
299
+ auto n{sprintf (buffer, " %+05d" , hrMin)};
300
+ return err ? 0 : n + 1 ;
301
+ #else
302
+ return std::strftime (buffer, buffSize, " %z" , localTime);
303
+ #endif
304
+ }
250
305
251
306
// SFINAE helper to return the struct tm.tm_gmtoff which is not a POSIX standard
252
307
// field.
@@ -263,8 +318,19 @@ GetGmtOffset(const TM &tm, fallback_implementation) {
263
318
// tm.tm_gmtoff is not available, there may be platform dependent alternatives
264
319
// (such as using timezone from <time.h> when available), but so far just
265
320
// return -HUGE to report that this information is not available.
266
- return -std::numeric_limits<Fortran::runtime::CppTypeFor<
267
- Fortran::common::TypeCategory::Integer, KIND>>::max ();
321
+ const auto negHuge{-std::numeric_limits<Fortran::runtime::CppTypeFor<
322
+ Fortran::common::TypeCategory::Integer, KIND>>::max ()};
323
+ #ifdef _AIX
324
+ bool err{false };
325
+ auto diff{computeUTCDiff (tm , &err)};
326
+ if (err) {
327
+ return negHuge;
328
+ } else {
329
+ return diff;
330
+ }
331
+ #else
332
+ return negHuge;
333
+ #endif
268
334
}
269
335
template <typename TM = struct tm > struct GmtOffsetHelper {
270
336
template <int KIND> struct StoreGmtOffset {
@@ -317,7 +383,7 @@ static void GetDateAndTime(Fortran::runtime::Terminator &terminator, char *date,
317
383
// Note: this may leave the buffer empty on many platforms. Classic flang
318
384
// has a much more complex way of doing this (see __io_timezone in classic
319
385
// flang).
320
- auto len{std::strftime (buffer, buffSize, " %z " , &localTime)};
386
+ auto len{getUTCOffsetToBuffer (buffer, buffSize, &localTime)};
321
387
copyBufferAndPad (zone, zoneChars, len);
322
388
}
323
389
if (values) {
0 commit comments