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, 675 Mass Ave, Cambridge, MA 02139, USA. */
26 static char tzname_default
[20]="";
27 static char tzname_dst
[20]="";
29 char *tzname
[2] = { tzname_default
, tzname_dst
};
31 static long internal_daylight
=0;
32 static char daylight_set
=0;
34 static long read_time(const char *nptr
, const char **endptr
,
41 /* This routine trusts the user very much, and does no checks!
42 The only exception is this: */
43 if (!sign_allowed_p
&& (*nptr
== '-' || *nptr
== '+'))
46 t
= strtol(*endptr
, endptr
, 10) * 3600;
47 if (**endptr
!= ':' || **endptr
== '+' || **endptr
== '-')
51 t
= t
+ strtol(*endptr
, endptr
, 10) * 60;
52 if (**endptr
!= ':' || **endptr
== '+' || **endptr
== '-')
56 return t
+ strtol(*endptr
, endptr
, 10);
59 static void read_dst_time(const char *nptr
, const char **endptr
,
60 int *m
, int *n
, int *d
,
63 time_t bintim
= time(0);
64 struct tm
*lc
= localtime(&bintim
);
67 *m
= 0; /* When m and n are 0, a Julian */
68 *n
= 0; /* date has been inserted in d */
74 /* This routine counts on the user to have specified "Mm.n.d",
75 where 1 <= n <= 5, 1 <= m <= 12, 0 <= d <= 6 */
77 *m
= strtol(++nptr
, endptr
, 10);
78 (*endptr
)++; /* Skip the dot */
79 *n
= strtol(*endptr
, endptr
, 10);
80 (*endptr
)++; /* Skip the dot */
81 *d
= strtol(*endptr
, endptr
, 10);
86 *leap_p
= 0; /* Never count with leap years */
87 default: /* trust the user to have inserted a number! */
88 *d
= strtol(++nptr
, endptr
, 10);
95 short year
, month
, day
, hour
, minute
, second
, centi_second
;
97 static void find_dst_time(int m
, int n
, long d
,
98 int hour
, int minute
, int second
,
100 long vms_internal_time
[2])
102 long status
= SYS$
GETTIM(vms_internal_time
);
103 struct vms_vectim vms_vectime
;
104 status
= SYS$
NUMTIM(&vms_vectime
, vms_internal_time
);
106 if (m
== 0 && n
== 0)
108 long tmp_vms_internal_time
[2][2];
110 long tmp_operation
= LIB$K_DAY_OF_YEAR
;
112 status
= LIB$
CVT_FROM_INTERNAL_TIME(&tmp_operation
, &day_of_year
,
115 vms_vectime
.month
= 2;
116 vms_vectime
.day
= 29;
117 status
= LIB$
CVT_VECTIM(&vms_vectime
, tmp_vms_internal_time
[0]);
118 if (status
& 1) /* This is a leap year */
120 if (!leap_p
&& d
> 59)
121 d
++; /* If we don't count with 29th Feb,
122 and this is a leap year, count up,
123 to make day 60 really become the
126 /* 1st January, at midnight */
127 vms_vectime
.month
= 1;
129 vms_vectime
.hour
= hour
;
130 vms_vectime
.minute
= minute
;
131 vms_vectime
.second
= second
;
132 vms_vectime
.centi_second
= 0;
133 status
= LIB$
CVT_VECTIM(&vms_vectime
, tmp_vms_internal_time
[0]);
134 tmp_operation
= LIB$K_DELTA_DAYS
;
135 status
= LIB$
CVT_TO_INTERNAL_TIME(&tmp_operation
, &d
,
136 tmp_vms_internal_time
[1]);
137 /* now, tmp_vms_interval_time[0] contains 1st Jan, 00:00:00,
138 and tmp_vms_interval_time[1] contains delta time +d days.
139 Let's just add them together */
140 status
= LIB$
ADD_TIMES(tmp_vms_internal_time
[0],
141 tmp_vms_internal_time
[1],
146 long tmp_vms_internal_time
[2];
148 long tmp_operation
= LIB$K_DAY_OF_YEAR
;
150 if (d
== 0) /* 0 is Sunday, which isn't compatible with VMS,
151 where day_of_week is 1 -- 7, and 1 is Monday */
153 d
= 7; /* So a simple conversion is required */
155 vms_vectime
.month
= m
;
157 vms_vectime
.hour
= hour
;
158 vms_vectime
.minute
= minute
;
159 vms_vectime
.second
= second
;
160 vms_vectime
.centi_second
= 0;
161 status
= LIB$
CVT_VECTIM(&vms_vectime
, tmp_vms_internal_time
);
162 tmp_operation
= LIB$K_DAY_OF_WEEK
;
163 status
= LIB$
CVT_FROM_INTERNAL_TIME(&tmp_operation
, &day_of_week
,
164 tmp_vms_internal_time
);
170 vms_vectime
.day
+= (n
-1)*7 + d
;
171 status
= LIB$
CVT_VECTIM(&vms_vectime
, vms_internal_time
);
174 vms_vectime
.day
-= 7; /* n was probably 5 */
175 status
= LIB$
CVT_VECTIM(&vms_vectime
, vms_internal_time
);
180 static cmp_vms_internal_times(long vms_internal_time1
[2],
181 long vms_internal_time2
[2])
183 if (vms_internal_time1
[1] < vms_internal_time2
[1])
186 if (vms_internal_time1
[1] > vms_internal_time2
[1])
189 if (vms_internal_time1
[0] < vms_internal_time2
[0])
192 if (vms_internal_time1
[0] > vms_internal_time2
[0])
198 /* -------------------------- Global routines ------------------------------ */
213 if ((TZ
= getenv("TZ")) == 0)
220 && (*p
<'0' || *p
> '9') && *p
!= '-' && *p
!= '+' && *p
!= ',')
224 /* This is special for VMS, so I don't care if it doesn't exist anywhere
227 timezone
= read_time(p
, &p
, 1);
232 && (*p
<'0' || *p
> '9') && *p
!= '-' && *p
!= '+' && *p
!= ',')
236 if (*p
!= '-' && *p
!= '+' && !(*p
>='0' && *p
<= '9'))
237 internal_daylight
= timezone
- 3600;
239 internal_daylight
= read_time(p
, &p
, 1);
247 int start_hour
=2, start_minute
=0, start_second
=0;
250 read_dst_time(p
, &p
, &start_m
, &start_n
, &start_d
, &start_leap_p
);
253 long tmp
= read_time (++p
, &p
, 0);
254 start_hour
= tmp
/ 3600;
255 start_minute
= (tmp
% 3600) / 60;
256 start_second
= tmp
% 60;
264 int end_hour
=2, end_minute
=0, end_second
=0;
267 read_dst_time(p
, &p
, &end_m
, &end_n
, &end_d
, &end_leap_p
);
270 long tmp
= read_time (++p
, &p
, 0);
271 end_hour
= tmp
/ 3600;
272 end_minute
= (tmp
% 3600) / 60;
273 end_second
= tmp
% 60;
276 long vms_internal_time
[3][2];
277 find_dst_time(start_m
, start_n
, start_d
,
278 start_hour
, start_minute
, start_second
,
280 vms_internal_time
[0]);
281 SYS$
GETTIM(&vms_internal_time
[1]);
282 find_dst_time(end_m
, end_n
, end_d
,
283 end_hour
, end_minute
, end_second
,
285 vms_internal_time
[2]);
286 if (cmp_vms_internal_times(vms_internal_time
[0],
287 vms_internal_time
[1]) < 0
288 && cmp_vms_internal_times(vms_internal_time
[1],
289 vms_internal_time
[2]) < 0)
299 struct tm
*sys_localtime(time_t *clock
)
301 struct tm
*tmp
= localtime(clock
);
304 tmp
->tm_isdst
= daylight
;
312 struct tm
*sys_gmtime(time_t *clock
)
314 static struct tm gmt
;
315 struct vms_vectim tmp_vectime
;
316 long vms_internal_time
[3][2];
317 long tmp_operation
= LIB$K_DELTA_SECONDS
;
325 tmp_offset
= internal_daylight
;
327 tmp_offset
= timezone
;
332 tmp_offset
= -tmp_offset
;
337 status
= LIB$
CVT_TO_INTERNAL_TIME(&tmp_operation
, &tmp_offset
,
338 vms_internal_time
[1]);
339 status
= SYS$
GETTIM(vms_internal_time
[0]);
342 status
= LIB$
SUB_TIMES(vms_internal_time
[0],
343 vms_internal_time
[1],
344 vms_internal_time
[2]);
348 status
= LIB$
ADD_TIMES(vms_internal_time
[0],
349 vms_internal_time
[1],
350 vms_internal_time
[2]);
353 status
= SYS$
NUMTIM(&tmp_vectime
, vms_internal_time
[2]);
354 gmt
.tm_sec
= tmp_vectime
.second
;
355 gmt
.tm_min
= tmp_vectime
.minute
;
356 gmt
.tm_hour
= tmp_vectime
.hour
;
357 gmt
.tm_mday
= tmp_vectime
.day
;
358 gmt
.tm_mon
= tmp_vectime
.month
- 1;
359 gmt
.tm_year
= tmp_vectime
.year
% 100;
361 tmp_operation
= LIB$K_DAY_OF_WEEK
;
362 status
= LIB$
CVT_FROM_INTERNAL_TIME(&tmp_operation
,
364 vms_internal_time
[2]);
365 if (gmt
.tm_wday
== 7) gmt
.tm_wday
= 0;
367 tmp_operation
= LIB$K_DAY_OF_YEAR
;
368 status
= LIB$
CVT_FROM_INTERNAL_TIME(&tmp_operation
,
370 vms_internal_time
[2]);
372 gmt
.tm_isdst
= daylight
;