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