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