1 /* Implementation of the DATE_AND_TIME intrinsic.
2 Copyright (C) 2003, 2004 Free Software Foundation, Inc.
3 Contributed by Steven Bosscher.
5 This file is part of the GNU Fortran 95 runtime library (libgfortran).
7 Libgfortran is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public
9 License as published by the Free Software Foundation; either
10 version 2 of the License, or (at your option) any later version.
12 In addition to the permissions in the GNU General Public License, the
13 Free Software Foundation gives you unlimited permission to link the
14 compiled version of this file into combinations with other programs,
15 and to distribute those combinations without any restriction coming
16 from the use of this file. (The General Public License restrictions
17 do apply in other respects; for example, they cover modification of
18 the file, and distribution when not linked into a combine
21 Libgfortran is distributed in the hope that it will be useful,
22 but WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 GNU General Public License for more details.
26 You should have received a copy of the GNU General Public
27 License along with libgfortran; see the file COPYING. If not,
28 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
29 Boston, MA 02111-1307, USA. */
32 #include <sys/types.h>
37 #include "libgfortran.h"
39 #undef HAVE_NO_DATE_TIME
40 #if TIME_WITH_SYS_TIME
41 # include <sys/time.h>
45 # include <sys/time.h>
50 # define HAVE_NO_DATE_TIME
51 # endif /* HAVE_TIME_H */
52 # endif /* HAVE_SYS_TIME_H */
53 #endif /* TIME_WITH_SYS_TIME */
56 #define abs(x) ((x)>=0 ? (x) : -(x))
59 /* DATE_AND_TIME ([DATE, TIME, ZONE, VALUES])
61 Description: Returns data on the real-time clock and date in a form
62 compatible with the representations defined in ISO 8601:1988.
64 Class: Non-elemental subroutine.
68 DATE (optional) shall be scalar and of type default character, and
69 shall be of length at least 8 in order to contain the complete
70 value. It is an INTENT (OUT) argument. Its leftmost 8 characters
71 are assigned a value of the form CCYYMMDD, where CC is the century,
72 YY the year within the century, MM the month within the year, and
73 DD the day within the month. If there is no date available, they
76 TIME (optional) shall be scalar and of type default character, and
77 shall be of length at least 10 in order to contain the complete
78 value. It is an INTENT (OUT) argument. Its leftmost 10 characters
79 are assigned a value of the form hhmmss.sss, where hh is the hour
80 of the day, mm is the minutes of the hour, and ss.sss is the
81 seconds and milliseconds of the minute. If there is no clock
82 available, they are assigned blanks.
84 ZONE (optional) shall be scalar and of type default character, and
85 shall be of length at least 5 in order to contain the complete
86 value. It is an INTENT (OUT) argument. Its leftmost 5 characters
87 are assigned a value of the form ±hhmm, where hh and mm are the
88 time difference with respect to Coordinated Universal Time (UTC) in
89 hours and parts of an hour expressed in minutes, respectively. If
90 there is no clock available, they are assigned blanks.
92 VALUES (optional) shall be of type default integer and of rank
93 one. It is an INTENT (OUT) argument. Its size shall be at least
94 8. The values returned in VALUES are as follows:
96 VALUES (1) the year (for example, 2003), or HUGE (0) if there is
99 VALUES (2) the month of the year, or HUGE (0) if there
100 is no date available;
102 VALUES (3) the day of the month, or HUGE (0) if there is no date
105 VALUES (4) the time difference with respect to Coordinated
106 Universal Time (UTC) in minutes, or HUGE (0) if this information
109 VALUES (5) the hour of the day, in the range of 0 to 23, or HUGE
110 (0) if there is no clock;
112 VALUES (6) the minutes of the hour, in the range 0 to 59, or
113 HUGE (0) if there is no clock;
115 VALUES (7) the seconds of the minute, in the range 0 to 60, or
116 HUGE (0) if there is no clock;
118 VALUES (8) the milliseconds of the second, in the range 0 to
119 999, or HUGE (0) if there is no clock.
121 NULL pointer represent missing OPTIONAL arguments. All arguments
122 have INTENT(OUT). Because of the -i8 option, we must implement
123 VALUES for INTEGER(kind=4) and INTEGER(kind=8).
125 Based on libU77's date_time_.c.
128 - Check year boundaries.
129 - There is no STDC/POSIX way to get VALUES(8). A GNUish way may
133 extern void date_and_time (char *, char *, char *, gfc_array_i4 *,
134 GFC_INTEGER_4, GFC_INTEGER_4, GFC_INTEGER_4);
135 export_proto(date_and_time);
138 date_and_time (char *__date,
141 gfc_array_i4 *__values,
142 GFC_INTEGER_4 __date_len,
143 GFC_INTEGER_4 __time_len,
144 GFC_INTEGER_4 __zone_len)
149 #define VALUES_SIZE 8
150 char date[DATE_LEN + 1];
151 char timec[TIME_LEN + 1];
152 char zone[ZONE_LEN + 1];
153 GFC_INTEGER_4 values[VALUES_SIZE];
155 #ifndef HAVE_NO_DATE_TIME
156 time_t lt = time (NULL);
157 struct tm local_time = *localtime (<);
158 struct tm UTC_time = *gmtime (<);
160 /* All arguments can be derived from VALUES. */
161 values[0] = 1900 + local_time.tm_year;
162 values[1] = 1 + local_time.tm_mon;
163 values[2] = local_time.tm_mday;
164 values[3] = (local_time.tm_min - UTC_time.tm_min +
165 60 * (local_time.tm_hour - UTC_time.tm_hour +
166 24 * (local_time.tm_yday - UTC_time.tm_yday)));
167 values[4] = local_time.tm_hour;
168 values[5] = local_time.tm_min;
169 values[6] = local_time.tm_sec;
170 #if HAVE_GETTIMEOFDAY
173 # if GETTIMEOFDAY_ONE_ARGUMENT
174 if (!gettimeofday (&tp))
176 # if HAVE_STRUCT_TIMEZONE
179 /* Some systems such as HP-UX, do have struct timezone, but
180 gettimeofday takes void* as the 2nd arg. However, the
181 effect of passing anything other than a null pointer is
182 unspecified on HPUX. Configure checks if gettimeofday
183 actually fails with a non-NULL arg and pretends that
184 struct timezone is missing if it does fail. */
185 if (!gettimeofday (&tp, &tzp))
187 if (!gettimeofday (&tp, (void *) 0))
188 # endif /* HAVE_STRUCT_TIMEZONE */
189 # endif /* GETTIMEOFDAY_ONE_ARGUMENT */
190 values[7] = tp.tv_usec / 1000;
193 values[7] = GFC_INTEGER_4_HUGE;
194 #endif /* HAVE_GETTIMEOFDAY */
199 snprintf (date, DATE_LEN + 1, "%04d%02d%02d",
200 values[0], values[1], values[2]);
202 sprintf (date, "%04d%02d%02d",
203 values[0], values[1], values[2]);
210 snprintf (timec, TIME_LEN + 1, "%02d%02d%02d.%03d",
211 values[4], values[5], values[6], values[7]);
213 sprintf (timec, "%02d%02d%02d.%03d",
214 values[4], values[5], values[6], values[7]);
221 snprintf (zone, ZONE_LEN + 1, "%+03d%02d",
222 values[3] / 60, abs (values[3] % 60));
224 sprintf (zone, "%+03d%02d",
225 values[3] / 60, abs (values[3] % 60));
228 #else /* if defined HAVE_NO_DATE_TIME */
229 /* We really have *nothing* to return, so return blanks and HUGE(0). */
233 memset (date, ' ', DATE_LEN);
234 date[DATE_LEN] = '\0';
236 memset (timec, ' ', TIME_LEN);
237 time[TIME_LEN] = '\0';
239 memset (zone, ' ', ZONE_LEN);
240 zone[ZONE_LEN] = '\0';
242 for (i = 0; i < VALUES_SIZE; i++)
243 values[i] = GFC_INTEGER_4_HUGE;
245 #endif /* HAVE_NO_DATE_TIME */
247 /* Copy the values into the arguments. */
251 size_t len, delta, elt_size;
253 elt_size = GFC_DESCRIPTOR_SIZE (__values);
254 len = __values->dim[0].ubound + 1 - __values->dim[0].lbound;
255 delta = __values->dim[0].stride;
259 assert (len >= VALUES_SIZE);
260 /* Cope with different type kinds. */
263 GFC_INTEGER_4 *vptr4 = __values->data;
265 for (i = 0; i < VALUES_SIZE; i++, vptr4 += delta)
270 else if (elt_size == 8)
272 GFC_INTEGER_8 *vptr8 = (GFC_INTEGER_8 *)__values->data;
274 for (i = 0; i < VALUES_SIZE; i++, vptr8 += delta)
276 if (values[i] == GFC_INTEGER_4_HUGE)
277 *vptr8 = GFC_INTEGER_8_HUGE;
288 assert (__zone_len >= ZONE_LEN);
289 fstrcpy (__zone, ZONE_LEN, zone, ZONE_LEN);
294 assert (__time_len >= TIME_LEN);
295 fstrcpy (__time, TIME_LEN, timec, TIME_LEN);
300 assert (__date_len >= DATE_LEN);
301 fstrcpy (__date, DATE_LEN, date, DATE_LEN);