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 8This file is part of RCS. 9 10RCS is free software; you can redistribute it and/or modify 11it under the terms of the GNU General Public License as published by 12the Free Software Foundation; either version 2, or (at your option) 13any later version. 14 15RCS is distributed in the hope that it will be useful, 16but WITHOUT ANY WARRANTY; without even the implied warranty of 17MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18GNU General Public License for more details. 19 20You should have received a copy of the GNU General Public License 21along with RCS; see the file COPYING. 22If not, write to the Free Software Foundation, 2359 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 24 25Report 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 35libId(rcstimeId, "Id: rcstime.c,v 1.4 1995/06/16 06:19:24 eggert Exp ") 36 37static long zone_offset; /* seconds east of UTC, or TM_LOCAL_ZONE */ 38static 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 46time2date(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. */ 64static time_t str2time_checked P((char const*,time_t,long)); 65 static time_t 66str2time_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 82str2date(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 98date2time(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 108zone_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 * 127date2str(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