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