xref: /netbsd/external/gpl2/rcs/dist/src/rcstime.c (revision 0d69c6cf)
1 /*	$NetBSD: rcstime.c,v 1.2 2016/01/14 04:22:39 christos Exp $	*/
2 
3 /* Convert between RCS time format and Posix and/or C formats.  */
4 
5 /* Copyright 1992, 1993, 1994, 1995 Paul Eggert
6    Distributed under license by the Free Software Foundation, Inc.
7 
8 This file is part of RCS.
9 
10 RCS is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2, or (at your option)
13 any later version.
14 
15 RCS is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 GNU General Public License for more details.
19 
20 You should have received a copy of the GNU General Public License
21 along with RCS; see the file COPYING.
22 If not, write to the Free Software Foundation,
23 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 
25 Report problems and direct all questions to:
26 
27     rcs-bugs@cs.purdue.edu
28 
29 */
30 
31 #include "rcsbase.h"
32 #include "partime.h"
33 #include "maketime.h"
34 
35 libId(rcstimeId, "Id: rcstime.c,v 1.4 1995/06/16 06:19:24 eggert Exp ")
36 
37 static long zone_offset; /* seconds east of UTC, or TM_LOCAL_ZONE */
38 static int use_zone_offset; /* if zero, use UTC without zone indication */
39 
40 /*
41 * Convert Unix time to RCS format.
42 * For compatibility with older versions of RCS,
43 * dates from 1900 through 1999 are stored without the leading "19".
44 */
45 	void
time2date(unixtime,date)46 time2date(unixtime,date)
47 	time_t unixtime;
48 	char date[datesize];
49 {
50 	register struct tm const *tm = time2tm(unixtime, RCSversion<VERSION(5));
51 	VOID sprintf(date,
52 #		if has_printf_dot
53 			"%.2d.%.2d.%.2d.%.2d.%.2d.%.2d",
54 #		else
55 			"%02d.%02d.%02d.%02d.%02d.%02d",
56 #		endif
57 		tm->tm_year  +  ((unsigned)tm->tm_year < 100 ? 0 : 1900),
58 		tm->tm_mon+1, tm->tm_mday,
59 		tm->tm_hour, tm->tm_min, tm->tm_sec
60 	);
61 }
62 
63 /* Like str2time, except die if an error was found.  */
64 static time_t str2time_checked P((char const*,time_t,long));
65 	static time_t
str2time_checked(source,default_time,default_zone)66 str2time_checked(source, default_time, default_zone)
67 	char const *source;
68 	time_t default_time;
69 	long default_zone;
70 {
71 	time_t t = str2time(source, default_time, default_zone);
72 	if (t == -1)
73 		faterror("unknown date/time: %s", source);
74 	return t;
75 }
76 
77 /*
78 * Parse a free-format date in SOURCE, convert it
79 * into RCS internal format, and store the result into TARGET.
80 */
81 	void
str2date(source,target)82 str2date(source, target)
83 	char const *source;
84 	char target[datesize];
85 {
86 	time2date(
87 		str2time_checked(source, now(),
88 			use_zone_offset ? zone_offset
89 			: RCSversion<VERSION(5) ? TM_LOCAL_ZONE
90 			: 0
91 		),
92 		target
93 	);
94 }
95 
96 /* Convert an RCS internal format date to time_t.  */
97 	time_t
date2time(source)98 date2time(source)
99 	char const source[datesize];
100 {
101 	char s[datesize + zonelenmax];
102 	return str2time_checked(date2str(source, s), (time_t)0, 0);
103 }
104 
105 
106 /* Set the time zone for date2str output.  */
107 	void
zone_set(s)108 zone_set(s)
109 	char const *s;
110 {
111 	if ((use_zone_offset = *s)) {
112 		long zone;
113 		char const *zonetail = parzone(s, &zone);
114 		if (!zonetail || *zonetail)
115 			error("%s: not a known time zone", s);
116 		else
117 			zone_offset = zone;
118 	}
119 }
120 
121 
122 /*
123 * Format a user-readable form of the RCS format DATE into the buffer DATEBUF.
124 * Yield DATEBUF.
125 */
126 	char const *
date2str(date,datebuf)127 date2str(date, datebuf)
128 	char const date[datesize];
129 	char datebuf[datesize + zonelenmax];
130 {
131 	register char const *p = date;
132 
133 	while (*p++ != '.')
134 		continue;
135 	if (!use_zone_offset)
136 	    VOID sprintf(datebuf,
137 		"19%.*s/%.2s/%.2s %.2s:%.2s:%s"
138 			+ (date[2]=='.' && VERSION(5)<=RCSversion  ?  0  :  2),
139 		(int)(p-date-1), date,
140 		p, p+3, p+6, p+9, p+12
141 	    );
142 	else {
143 	    struct tm t;
144 	    struct tm const *z;
145 	    int non_hour;
146 	    long zone;
147 	    char c;
148 
149 	    t.tm_year = atoi(date) - (date[2]=='.' ? 0 : 1900);
150 	    t.tm_mon = atoi(p) - 1;
151 	    t.tm_mday = atoi(p+3);
152 	    t.tm_hour = atoi(p+6);
153 	    t.tm_min = atoi(p+9);
154 	    t.tm_sec = atoi(p+12);
155 	    t.tm_wday = -1;
156 	    zone = zone_offset;
157 	    if (zone == TM_LOCAL_ZONE) {
158 		time_t u = tm2time(&t, 0), d;
159 		z = localtime(&u);
160 		d = difftm(z, &t);
161 		zone  =  (time_t)-1 < 0 || d < -d  ?  d  :  -(long)-d;
162 	    } else {
163 		adjzone(&t, zone);
164 		z = &t;
165 	    }
166 	    c = '+';
167 	    if (zone < 0) {
168 		zone = -zone;
169 		c = '-';
170 	    }
171 	    VOID sprintf(datebuf,
172 #		if has_printf_dot
173 		    "%.2d-%.2d-%.2d %.2d:%.2d:%.2d%c%.2d",
174 #		else
175 		    "%02d-%02d-%02d %02d:%02d:%02d%c%02d",
176 #		endif
177 		z->tm_year + 1900,
178 		z->tm_mon + 1, z->tm_mday, z->tm_hour, z->tm_min, z->tm_sec,
179 		c, (int) (zone / (60*60))
180 	    );
181 	    if ((non_hour = zone % (60*60))) {
182 #		if has_printf_dot
183 		    static char const fmt[] = ":%.2d";
184 #		else
185 		    static char const fmt[] = ":%02d";
186 #		endif
187 		VOID sprintf(datebuf + strlen(datebuf), fmt, non_hour / 60);
188 		if ((non_hour %= 60))
189 		    VOID sprintf(datebuf + strlen(datebuf), fmt, non_hour);
190 	    }
191 	}
192 	return datebuf;
193 }
194