@@ -2,7 +2,7 @@ module datetime_module
22
33 use , intrinsic :: iso_fortran_env, only: int64, real32, real64, &
44 stderr = > error_unit
5- use , intrinsic :: iso_c_binding, only: c_char, c_int, c_null_char, c_associated, C_PTR
5+ use , intrinsic :: iso_c_binding, only: c_char, c_int, c_int64_t, c_null_char, c_associated, C_PTR
66
77 implicit none
88
@@ -15,7 +15,11 @@ module datetime_module
1515 public :: daysInYear
1616 public :: isLeapYear
1717 public :: num2date
18+ public :: machinetimezone
1819 public :: strptime
20+ public :: epochdatetime
21+ public :: localtime
22+ public :: gmtime
1923 public :: tm2date
2024 public :: tm_struct
2125 public :: c_strftime
@@ -178,7 +182,7 @@ module datetime_module
178182
179183 interface
180184
181- type (C_PTR ) function c_strftime(str, slen, format , tm) bind(c, name= ' strftime' )
185+ type (c_ptr ) function c_strftime(str, slen, format , tm) bind(c, name= ' strftime' )
182186 ! Returns a formatted time string, given input time struct and format.
183187 ! See https://www.cplusplus.com/reference/ctime/strftime for reference.
184188 import :: c_char, c_int, tm_struct, C_PTR
@@ -644,13 +648,34 @@ integer(int64) function secondsSinceEpoch(self)
644648 class(datetime), intent (in ) :: self
645649 type (timedelta) :: delta
646650 type (datetime) :: this_time, unix_time
651+ integer :: sign, hours, minutes, tzsec
647652
648653 this_time = datetime(self% year, self% month, self% day, &
649654 self% hour, self% minute, self% second)
650655 unix_time = datetime(1970 , 1 , 1 , 0 , 0 , 0 )
651656 delta = this_time - unix_time
652657 secondsSinceEpoch = delta% total_seconds()
653658
659+ if (self % tz == 0_real64 ) return
660+
661+ ! affect timezone information
662+ if (self % tz < 0_real64 ) then
663+ sign = - 1
664+ else
665+ sign = 1
666+ end if
667+
668+ hours = int (abs (self % tz))
669+ minutes = nint ((abs (self % tz) - hours) * 60 )
670+
671+ if (minutes == 60 ) then
672+ minutes = 0
673+ hours = hours + 1
674+ end if
675+
676+ tzsec = sign * (hours * h2s + minutes)
677+ secondsSinceEpoch = secondsSinceEpoch - tzsec
678+
654679 end function secondsSinceEpoch
655680
656681
@@ -1098,25 +1123,88 @@ pure elemental type(datetime) function num2date(num)
10981123 end function num2date
10991124
11001125
1101- type(datetime) function strptime (str ,format )
1126+ real (real64) function machinetimezone()
1127+ ! Return a real value instance of local machine's timezone.
1128+ character (len= 5 ) :: zone
1129+ integer :: values(8 )
1130+ integer :: hour, minute
1131+
1132+ ! Obtain local machine time zone information
1133+ call date_and_time (zone= zone, values= values)
1134+ read (zone(1 :3 ), ' (i3)' ) hour
1135+ read (zone(4 :5 ), ' (i2)' ) minute
1136+
1137+ if (hour< 0 )then
1138+ machinetimezone = real (hour, kind= real64) - real (minute, kind= real64) * m2h
1139+ else
1140+ machinetimezone = real (hour, kind= real64) + real (minute, kind= real64) * m2h
1141+ end if
1142+ end function machinetimezone
1143+
1144+
1145+ type(datetime) function strptime (str ,format ,tz )
11021146 ! A wrapper function around C/C++ strptime function.
11031147 ! Returns a `datetime` instance.
11041148 character (* ), intent (in ) :: str, format
1149+ real (real64), intent (in ), optional :: tz
11051150 integer :: rc
11061151 type (tm_struct) :: tm
11071152 rc = c_strptime(trim (str) // c_null_char, trim (format ) // c_null_char, tm)
11081153 if (rc == 0 ) then
11091154 write (stderr, * ) " ERROR:datetime:strptime: failed to parse string: " , str
11101155 return
11111156 endif
1112- strptime = tm2date(tm)
1157+ strptime = tm2date(tm,tz )
11131158 end function strptime
11141159
11151160
1116- pure elemental type (datetime) function tm2date(ctime)
1161+ pure elemental type (datetime) function epochdatetime()
1162+ epochdatetime = datetime(1970 ,1 ,1 ,0 ,0 ,0 ,0 ,tz= zero)
1163+ end function epochdatetime
1164+
1165+
1166+ pure elemental type (datetime) function localtime(epoch, tz)
1167+ ! Returns a `datetime` instance from epoch.
1168+ ! tz can be obtained from `machinetimezone`
1169+ integer (int64),intent (in ) :: epoch
1170+ real (real64),intent (in ) :: tz ! ! local machine time zone information
1171+ type (datetime) :: datetime_from_epoch
1172+ type (timedelta) :: td
1173+ integer :: day, sec
1174+ integer (int64) :: localseconds
1175+
1176+ datetime_from_epoch = epochdatetime()
1177+
1178+ localseconds = nint (tz * h2s) + epoch
1179+ ! suppress overflow
1180+ day = floor (localseconds/ d2s, kind= real32)
1181+ sec = localseconds - day * d2s
1182+ td = timedelta(days= day, seconds= sec)
1183+ datetime_from_epoch % tz = tz
1184+ localtime = datetime_from_epoch + td
1185+ end function localtime
1186+
1187+
1188+ pure elemental type (datetime) function gmtime(epoch)
1189+ ! Returns a `datetime` instance from epoch.
1190+ integer (int64),intent (in ) :: epoch
1191+ type (datetime) :: datetime_from_epoch
1192+ type (timedelta) :: td
1193+ integer :: day, sec
1194+ datetime_from_epoch = epochdatetime()
1195+ ! suppress overflow
1196+ day = floor (epoch/ d2s, kind= real32)
1197+ sec = epoch - day * d2s
1198+ td = timedelta(days= day, seconds= sec)
1199+ gmtime = datetime_from_epoch + td
1200+ end function gmtime
1201+
1202+
1203+ pure elemental type (datetime) function tm2date(ctime, tz)
11171204 ! Given a `tm_struct` instance, returns a corresponding `datetime`
11181205 ! instance.
11191206 type (tm_struct), intent (in ) :: ctime
1207+ real (real64), intent (in ), optional :: tz ! time zone
11201208
11211209 tm2date % millisecond = 0
11221210 tm2date % second = ctime % tm_sec
@@ -1125,7 +1213,17 @@ pure elemental type(datetime) function tm2date(ctime)
11251213 tm2date % day = ctime % tm_mday
11261214 tm2date % month = ctime % tm_mon+1
11271215 tm2date % year = ctime % tm_year+1900
1128- tm2date % tz = 0
1216+
1217+ ! tm_struct have no information of timze zone.
1218+ ! but if you run this library with C language's time.h,
1219+ ! localtime function deals system's timezone.
1220+ ! So, if you want to similar way, you can set tz value with
1221+ ! this library's `machinetimezone` function.
1222+ if (present (tz))then
1223+ tm2date % tz = tz
1224+ else
1225+ tm2date % tz = 0.0_real64
1226+ end if
11291227
11301228 end function tm2date
11311229
0 commit comments