@@ -2,7 +2,7 @@ module datetime_module
2
2
3
3
use , intrinsic :: iso_fortran_env, only: int64, real32, real64, &
4
4
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
6
6
7
7
implicit none
8
8
@@ -15,7 +15,11 @@ module datetime_module
15
15
public :: daysInYear
16
16
public :: isLeapYear
17
17
public :: num2date
18
+ public :: machinetimezone
18
19
public :: strptime
20
+ public :: epochdatetime
21
+ public :: localtime
22
+ public :: gmtime
19
23
public :: tm2date
20
24
public :: tm_struct
21
25
public :: c_strftime
@@ -178,7 +182,7 @@ module datetime_module
178
182
179
183
interface
180
184
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' )
182
186
! Returns a formatted time string, given input time struct and format.
183
187
! See https://www.cplusplus.com/reference/ctime/strftime for reference.
184
188
import :: c_char, c_int, tm_struct, C_PTR
@@ -644,13 +648,34 @@ integer(int64) function secondsSinceEpoch(self)
644
648
class(datetime), intent (in ) :: self
645
649
type (timedelta) :: delta
646
650
type (datetime) :: this_time, unix_time
651
+ integer :: sign, hours, minutes, tzsec
647
652
648
653
this_time = datetime(self% year, self% month, self% day, &
649
654
self% hour, self% minute, self% second)
650
655
unix_time = datetime(1970 , 1 , 1 , 0 , 0 , 0 )
651
656
delta = this_time - unix_time
652
657
secondsSinceEpoch = delta% total_seconds()
653
658
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
+
654
679
end function secondsSinceEpoch
655
680
656
681
@@ -1098,25 +1123,88 @@ pure elemental type(datetime) function num2date(num)
1098
1123
end function num2date
1099
1124
1100
1125
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 )
1102
1146
! A wrapper function around C/C++ strptime function.
1103
1147
! Returns a `datetime` instance.
1104
1148
character (* ), intent (in ) :: str, format
1149
+ real (real64), intent (in ), optional :: tz
1105
1150
integer :: rc
1106
1151
type (tm_struct) :: tm
1107
1152
rc = c_strptime(trim (str) // c_null_char, trim (format ) // c_null_char, tm)
1108
1153
if (rc == 0 ) then
1109
1154
write (stderr, * ) " ERROR:datetime:strptime: failed to parse string: " , str
1110
1155
return
1111
1156
endif
1112
- strptime = tm2date(tm)
1157
+ strptime = tm2date(tm,tz )
1113
1158
end function strptime
1114
1159
1115
1160
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)
1117
1204
! Given a `tm_struct` instance, returns a corresponding `datetime`
1118
1205
! instance.
1119
1206
type (tm_struct), intent (in ) :: ctime
1207
+ real (real64), intent (in ), optional :: tz ! time zone
1120
1208
1121
1209
tm2date % millisecond = 0
1122
1210
tm2date % second = ctime % tm_sec
@@ -1125,7 +1213,17 @@ pure elemental type(datetime) function tm2date(ctime)
1125
1213
tm2date % day = ctime % tm_mday
1126
1214
tm2date % month = ctime % tm_mon+1
1127
1215
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
1129
1227
1130
1228
end function tm2date
1131
1229
0 commit comments