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 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 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 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 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 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 * 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