111891Speter/* Convert between RCS time format and Posix and/or C formats. */ 211891Speter 311891Speter/* Copyright 1992, 1993, 1994, 1995 Paul Eggert 411891Speter Distributed under license by the Free Software Foundation, Inc. 511891Speter 611891SpeterThis file is part of RCS. 711891Speter 811891SpeterRCS is free software; you can redistribute it and/or modify 911891Speterit under the terms of the GNU General Public License as published by 1011891Speterthe Free Software Foundation; either version 2, or (at your option) 1111891Speterany later version. 1211891Speter 1311891SpeterRCS is distributed in the hope that it will be useful, 1411891Speterbut WITHOUT ANY WARRANTY; without even the implied warranty of 1511891SpeterMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1611891SpeterGNU General Public License for more details. 1711891Speter 1811891SpeterYou should have received a copy of the GNU General Public License 1911891Speteralong with RCS; see the file COPYING. 2011891SpeterIf not, write to the Free Software Foundation, 2111891Speter59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 2211891Speter 2311891SpeterReport problems and direct all questions to: 2411891Speter 2511891Speter rcs-bugs@cs.purdue.edu 2611891Speter 2711891Speter*/ 2811891Speter 2911891Speter#include "rcsbase.h" 3011891Speter#include "partime.h" 3111891Speter#include "maketime.h" 3211891Speter 3350472SpeterlibId(rcstimeId, "$FreeBSD$") 3411891Speter 3511891Speterstatic long zone_offset; /* seconds east of UTC, or TM_LOCAL_ZONE */ 3611891Speterstatic int use_zone_offset; /* if zero, use UTC without zone indication */ 3711891Speter 3811891Speter/* 3911891Speter* Convert Unix time to RCS format. 4011891Speter* For compatibility with older versions of RCS, 4111891Speter* dates from 1900 through 1999 are stored without the leading "19". 4211891Speter*/ 4311891Speter void 4411891Spetertime2date(unixtime,date) 4511891Speter time_t unixtime; 4611891Speter char date[datesize]; 4711891Speter{ 4811891Speter register struct tm const *tm = time2tm(unixtime, RCSversion<VERSION(5)); 4911891Speter VOID sprintf(date, 5011891Speter# if has_printf_dot 5111891Speter "%.2d.%.2d.%.2d.%.2d.%.2d.%.2d", 5211891Speter# else 5311891Speter "%02d.%02d.%02d.%02d.%02d.%02d", 5411891Speter# endif 5511891Speter tm->tm_year + ((unsigned)tm->tm_year < 100 ? 0 : 1900), 5611891Speter tm->tm_mon+1, tm->tm_mday, 5711891Speter tm->tm_hour, tm->tm_min, tm->tm_sec 5811891Speter ); 5911891Speter} 6011891Speter 6111891Speter/* Like str2time, except die if an error was found. */ 6211891Speterstatic time_t str2time_checked P((char const*,time_t,long)); 6311891Speter static time_t 6411891Speterstr2time_checked(source, default_time, default_zone) 6511891Speter char const *source; 6611891Speter time_t default_time; 6711891Speter long default_zone; 6811891Speter{ 6911891Speter time_t t = str2time(source, default_time, default_zone); 7011891Speter if (t == -1) 7111891Speter faterror("unknown date/time: %s", source); 7211891Speter return t; 7311891Speter} 7411891Speter 7511891Speter/* 7611891Speter* Parse a free-format date in SOURCE, convert it 7711891Speter* into RCS internal format, and store the result into TARGET. 7811891Speter*/ 7911891Speter void 8011891Speterstr2date(source, target) 8111891Speter char const *source; 8211891Speter char target[datesize]; 8311891Speter{ 8411891Speter time2date( 8511891Speter str2time_checked(source, now(), 8611891Speter use_zone_offset ? zone_offset 8711891Speter : RCSversion<VERSION(5) ? TM_LOCAL_ZONE 8811891Speter : 0 8911891Speter ), 9011891Speter target 9111891Speter ); 9211891Speter} 9311891Speter 9411891Speter/* Convert an RCS internal format date to time_t. */ 9511891Speter time_t 9611891Speterdate2time(source) 9711891Speter char const source[datesize]; 9811891Speter{ 9911891Speter char s[datesize + zonelenmax]; 10011891Speter return str2time_checked(date2str(source, s), (time_t)0, 0); 10111891Speter} 10211891Speter 10311891Speter 10411891Speter/* Set the time zone for date2str output. */ 10511891Speter void 10611891Speterzone_set(s) 10711891Speter char const *s; 10811891Speter{ 10911891Speter if ((use_zone_offset = *s)) { 11011891Speter long zone; 11111891Speter char const *zonetail = parzone(s, &zone); 11211891Speter if (!zonetail || *zonetail) 11311891Speter error("%s: not a known time zone", s); 11411891Speter else 11511891Speter zone_offset = zone; 11611891Speter } 11711891Speter} 11811891Speter 11911891Speter 12011891Speter/* 12111891Speter* Format a user-readable form of the RCS format DATE into the buffer DATEBUF. 12211891Speter* Yield DATEBUF. 12311891Speter*/ 12411891Speter char const * 12511891Speterdate2str(date, datebuf) 12611891Speter char const date[datesize]; 12711891Speter char datebuf[datesize + zonelenmax]; 12811891Speter{ 12911891Speter register char const *p = date; 13011891Speter 13111891Speter while (*p++ != '.') 13211891Speter continue; 13311891Speter if (!use_zone_offset) 13411891Speter VOID sprintf(datebuf, 13511891Speter "19%.*s/%.2s/%.2s %.2s:%.2s:%s" 13611891Speter + (date[2]=='.' && VERSION(5)<=RCSversion ? 0 : 2), 13711891Speter (int)(p-date-1), date, 13811891Speter p, p+3, p+6, p+9, p+12 13911891Speter ); 14011891Speter else { 14111891Speter struct tm t; 14211891Speter struct tm const *z; 14311891Speter int non_hour; 14411891Speter long zone; 14511891Speter char c; 14611891Speter 14711891Speter t.tm_year = atoi(date) - (date[2]=='.' ? 0 : 1900); 14811891Speter t.tm_mon = atoi(p) - 1; 14911891Speter t.tm_mday = atoi(p+3); 15011891Speter t.tm_hour = atoi(p+6); 15111891Speter t.tm_min = atoi(p+9); 15211891Speter t.tm_sec = atoi(p+12); 15311891Speter t.tm_wday = -1; 15411891Speter zone = zone_offset; 15511891Speter if (zone == TM_LOCAL_ZONE) { 15611891Speter time_t u = tm2time(&t, 0), d; 15711891Speter z = localtime(&u); 15811891Speter d = difftm(z, &t); 15911891Speter zone = (time_t)-1 < 0 || d < -d ? d : -(long)-d; 16011891Speter } else { 16111891Speter adjzone(&t, zone); 16211891Speter z = &t; 16311891Speter } 16411891Speter c = '+'; 16511891Speter if (zone < 0) { 16611891Speter zone = -zone; 16711891Speter c = '-'; 16811891Speter } 16911891Speter VOID sprintf(datebuf, 17011891Speter# if has_printf_dot 17111891Speter "%.2d-%.2d-%.2d %.2d:%.2d:%.2d%c%.2d", 17211891Speter# else 17311891Speter "%02d-%02d-%02d %02d:%02d:%02d%c%02d", 17411891Speter# endif 17511891Speter z->tm_year + 1900, 17611891Speter z->tm_mon + 1, z->tm_mday, z->tm_hour, z->tm_min, z->tm_sec, 17711891Speter c, (int) (zone / (60*60)) 17811891Speter ); 17911891Speter if ((non_hour = zone % (60*60))) { 18011891Speter# if has_printf_dot 18111891Speter static char const fmt[] = ":%.2d"; 18211891Speter# else 18311891Speter static char const fmt[] = ":%02d"; 18411891Speter# endif 18511891Speter VOID sprintf(datebuf + strlen(datebuf), fmt, non_hour / 60); 18611891Speter if ((non_hour %= 60)) 18711891Speter VOID sprintf(datebuf + strlen(datebuf), fmt, non_hour); 18811891Speter } 18911891Speter } 19011891Speter return datebuf; 19111891Speter} 192