1 /* Time support for VMS.
2 Copyright (C) 1993 Free Software Foundation.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
27 static char tzname_default
[20]="";
28 static char tzname_dst
[20]="";
30 char *tzname
[2] = { tzname_default
, tzname_dst
};
32 static long internal_daylight
=0;
33 static char daylight_set
=0;
35 static long read_time(const char *nptr
, const char **endptr
,
42 /* This routine trusts the user very much, and does no checks!
43 The only exception is this: */
44 if (!sign_allowed_p
&& (*nptr
== '-' || *nptr
== '+'))
47 t
= strtol(*endptr
, endptr
, 10) * 3600;
48 if (**endptr
!= ':' || **endptr
== '+' || **endptr
== '-')
52 t
= t
+ strtol(*endptr
, endptr
, 10) * 60;
53 if (**endptr
!= ':' || **endptr
== '+' || **endptr
== '-')
57 return t
+ strtol(*endptr
, endptr
, 10);
60 static void read_dst_time(const char *nptr
, const char **endptr
,
61 int *m
, int *n
, int *d
,
64 time_t bintim
= time(0);
65 struct tm
*lc
= localtime(&bintim
);
68 *m
= 0; /* When m and n are 0, a Julian */
69 *n
= 0; /* date has been inserted in d */
75 /* This routine counts on the user to have specified "Mm.n.d",
76 where 1 <= n <= 5, 1 <= m <= 12, 0 <= d <= 6 */
78 *m
= strtol(++nptr
, endptr
, 10);
79 (*endptr
)++; /* Skip the dot */
80 *n
= strtol(*endptr
, endptr
, 10);
81 (*endptr
)++; /* Skip the dot */
82 *d
= strtol(*endptr
, endptr
, 10);
87 *leap_p
= 0; /* Never count with leap years */
88 default: /* trust the user to have inserted a number! */
89 *d
= strtol(++nptr
, endptr
, 10);
96 short year
, month
, day
, hour
, minute
, second
, centi_second
;
98 static void find_dst_time(int m
, int n
, long d
,
99 int hour
, int minute
, int second
,
101 long vms_internal_time
[2])
103 long status
= SYS$
GETTIM(vms_internal_time
);
104 struct vms_vectim vms_vectime
;
105 status
= SYS$
NUMTIM(&vms_vectime
, vms_internal_time
);
107 if (m
== 0 && n
== 0)
109 long tmp_vms_internal_time
[2][2];
111 long tmp_operation
= LIB$K_DAY_OF_YEAR
;
113 status
= LIB$
CVT_FROM_INTERNAL_TIME(&tmp_operation
, &day_of_year
,
116 vms_vectime
.month
= 2;
117 vms_vectime
.day
= 29;
118 status
= LIB$
CVT_VECTIM(&vms_vectime
, tmp_vms_internal_time
[0]);
119 if (status
& 1) /* This is a leap year */
121 if (!leap_p
&& d
> 59)
122 d
++; /* If we don't count with 29th Feb,
123 and this is a leap year, count up,
124 to make day 60 really become the
127 /* 1st January, at midnight */
128 vms_vectime
.month
= 1;
130 vms_vectime
.hour
= hour
;
131 vms_vectime
.minute
= minute
;
132 vms_vectime
.second
= second
;
133 vms_vectime
.centi_second
= 0;
134 status
= LIB$
CVT_VECTIM(&vms_vectime
, tmp_vms_internal_time
[0]);
135 tmp_operation
= LIB$K_DELTA_DAYS
;
136 status
= LIB$
CVT_TO_INTERNAL_TIME(&tmp_operation
, &d
,
137 tmp_vms_internal_time
[1]);
138 /* now, tmp_vms_interval_time[0] contains 1st Jan, 00:00:00,
139 and tmp_vms_interval_time[1] contains delta time +d days.
140 Let's just add them together */
141 status
= LIB$
ADD_TIMES(tmp_vms_internal_time
[0],
142 tmp_vms_internal_time
[1],
147 long tmp_vms_internal_time
[2];
149 long tmp_operation
= LIB$K_DAY_OF_YEAR
;
151 if (d
== 0) /* 0 is Sunday, which isn't compatible with VMS,
152 where day_of_week is 1 -- 7, and 1 is Monday */
154 d
= 7; /* So a simple conversion is required */
156 vms_vectime
.month
= m
;
158 vms_vectime
.hour
= hour
;
159 vms_vectime
.minute
= minute
;
160 vms_vectime
.second
= second
;
161 vms_vectime
.centi_second
= 0;
162 status
= LIB$
CVT_VECTIM(&vms_vectime
, tmp_vms_internal_time
);
163 tmp_operation
= LIB$K_DAY_OF_WEEK
;
164 status
= LIB$
CVT_FROM_INTERNAL_TIME(&tmp_operation
, &day_of_week
,
165 tmp_vms_internal_time
);
171 vms_vectime
.day
+= (n
-1)*7 + d
;
172 status
= LIB$
CVT_VECTIM(&vms_vectime
, vms_internal_time
);
175 vms_vectime
.day
-= 7; /* n was probably 5 */
176 status
= LIB$
CVT_VECTIM(&vms_vectime
, vms_internal_time
);
181 static cmp_vms_internal_times(long vms_internal_time1
[2],
182 long vms_internal_time2
[2])
184 if (vms_internal_time1
[1] < vms_internal_time2
[1])
187 if (vms_internal_time1
[1] > vms_internal_time2
[1])
190 if (vms_internal_time1
[0] < vms_internal_time2
[0])
193 if (vms_internal_time1
[0] > vms_internal_time2
[0])
199 /* -------------------------- Global routines ------------------------------ */
214 if ((TZ
= getenv("TZ")) == 0)
221 && (*p
<'0' || *p
> '9') && *p
!= '-' && *p
!= '+' && *p
!= ',')
225 /* This is special for VMS, so I don't care if it doesn't exist anywhere
228 timezone
= read_time(p
, &p
, 1);
233 && (*p
<'0' || *p
> '9') && *p
!= '-' && *p
!= '+' && *p
!= ',')
237 if (*p
!= '-' && *p
!= '+' && !(*p
>='0' && *p
<= '9'))
238 internal_daylight
= timezone
- 3600;
240 internal_daylight
= read_time(p
, &p
, 1);
248 int start_hour
=2, start_minute
=0, start_second
=0;
251 read_dst_time(p
, &p
, &start_m
, &start_n
, &start_d
, &start_leap_p
);
254 long tmp
= read_time (++p
, &p
, 0);
255 start_hour
= tmp
/ 3600;
256 start_minute
= (tmp
% 3600) / 60;
257 start_second
= tmp
% 60;
265 int end_hour
=2, end_minute
=0, end_second
=0;
268 read_dst_time(p
, &p
, &end_m
, &end_n
, &end_d
, &end_leap_p
);
271 long tmp
= read_time (++p
, &p
, 0);
272 end_hour
= tmp
/ 3600;
273 end_minute
= (tmp
% 3600) / 60;
274 end_second
= tmp
% 60;
277 long vms_internal_time
[3][2];
278 find_dst_time(start_m
, start_n
, start_d
,
279 start_hour
, start_minute
, start_second
,
281 vms_internal_time
[0]);
282 SYS$
GETTIM(&vms_internal_time
[1]);
283 find_dst_time(end_m
, end_n
, end_d
,
284 end_hour
, end_minute
, end_second
,
286 vms_internal_time
[2]);
287 if (cmp_vms_internal_times(vms_internal_time
[0],
288 vms_internal_time
[1]) < 0
289 && cmp_vms_internal_times(vms_internal_time
[1],
290 vms_internal_time
[2]) < 0)
300 struct tm
*sys_localtime(time_t *clock
)
302 struct tm
*tmp
= localtime(clock
);
305 tmp
->tm_isdst
= daylight
;
313 struct tm
*sys_gmtime(time_t *clock
)
315 static struct tm gmt
;
316 struct vms_vectim tmp_vectime
;
317 long vms_internal_time
[3][2];
318 long tmp_operation
= LIB$K_DELTA_SECONDS
;
326 tmp_offset
= internal_daylight
;
328 tmp_offset
= timezone
;
333 tmp_offset
= -tmp_offset
;
338 status
= LIB$
CVT_TO_INTERNAL_TIME(&tmp_operation
, &tmp_offset
,
339 vms_internal_time
[1]);
340 status
= SYS$
GETTIM(vms_internal_time
[0]);
343 status
= LIB$
SUB_TIMES(vms_internal_time
[0],
344 vms_internal_time
[1],
345 vms_internal_time
[2]);
349 status
= LIB$
ADD_TIMES(vms_internal_time
[0],
350 vms_internal_time
[1],
351 vms_internal_time
[2]);
354 status
= SYS$
NUMTIM(&tmp_vectime
, vms_internal_time
[2]);
355 gmt
.tm_sec
= tmp_vectime
.second
;
356 gmt
.tm_min
= tmp_vectime
.minute
;
357 gmt
.tm_hour
= tmp_vectime
.hour
;
358 gmt
.tm_mday
= tmp_vectime
.day
;
359 gmt
.tm_mon
= tmp_vectime
.month
- 1;
360 gmt
.tm_year
= tmp_vectime
.year
- 1900;
362 tmp_operation
= LIB$K_DAY_OF_WEEK
;
363 status
= LIB$
CVT_FROM_INTERNAL_TIME(&tmp_operation
,
365 vms_internal_time
[2]);
366 if (gmt
.tm_wday
== 7) gmt
.tm_wday
= 0;
368 tmp_operation
= LIB$K_DAY_OF_YEAR
;
369 status
= LIB$
CVT_FROM_INTERNAL_TIME(&tmp_operation
,
371 vms_internal_time
[2]);
373 gmt
.tm_isdst
= daylight
;