[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
$DateZone: (ZONE)$ (was RE: $DateLocal$)
From: |
KOIE Hidetaka |
Subject: |
$DateZone: (ZONE)$ (was RE: $DateLocal$) |
Date: |
Mon, 18 Jun 2001 19:28:59 +0900 |
I come again,
implement `$DateZone: (ZONENAME)$'.
From: address@hidden (Larry Jones)
Subject: Re: $DateLocal$
Date: Sat, 16 Jun 2001 00:37:51 +0900
Message-Id: <address@hidden>
| KOIE Hidetaka writes:
| >
| > I implement $DateLocal$ keyword expansion using strftime().
| > Is this a bad idea?
|
| Probably:
|
| 1) The "local" time you're using is the local time of the server, not
| the local time of the client.
In this implementation, a writer specifies the timezone.
Then, the behavior is a place-independent.
| 2) Your code assumes that the differential between local time and UTC is
| always the same as it is currently, which isn't true for all of us that
| have "daylight saving" or "summer" time.
A problem of this implementation is
the literal ZONENAME depends on OS.
How to check what literal accepts, try "env TZ=ZONENAME date".
In freebsd and linux, look under /usr/share/zoneinfo.
In Solaris, /usr/share/lib/zoneinfo. For example:
I'm in Japan and uses freebsd, then
write "$DateZone: (Asia/Tokyo) 2001/06/18 19:10:22 JST $".
Note: SPACE must be placed after colon for the program ident in RCS.
I dont know about summer time,
because no summer time in Japan, sorry.
I'm hoping for solved.
--
KOIE Hidetaka <address@hidden> in Japan.
Index: lib/getdate.c
===================================================================
RCS file: /home2/cvsroot/ccvs/lib/getdate.c,v
retrieving revision 1.21
diff -u -p -r1.21 getdate.c
--- lib/getdate.c 2 Apr 2001 19:10:15 -0000 1.21
+++ lib/getdate.c 18 Jun 2001 10:16:43 -0000
@@ -1660,7 +1660,17 @@ Convert(Month, Day, Year, Hours, Minutes
Julian -= 60 * 60;
return Julian;
}
-
+time_t
+convert_date(Month, Day, Year, Hours, Minutes, Seconds)
+ time_t Month;
+ time_t Day;
+ time_t Year;
+ time_t Hours;
+ time_t Minutes;
+ time_t Seconds;
+{
+ return Convert(Month, Day, Year, Hours, Minutes, Seconds, MER24, DSTmaybe);
+}
static time_t
DSTcorrect(Start, Future)
Index: src/cvs.h
===================================================================
RCS file: /home2/cvsroot/ccvs/src/cvs.h,v
retrieving revision 1.222
diff -u -p -r1.222 cvs.h
--- src/cvs.h 25 May 2001 14:48:08 -0000 1.222
+++ src/cvs.h 18 Jun 2001 10:16:43 -0000
@@ -493,6 +493,8 @@ int update PROTO((int argc, char *argv[]
int xcmp PROTO((const char *file1, const char *file2));
int yesno PROTO((void));
void *valloc PROTO((size_t bytes));
+time_t convert_date(time_t Month, time_t Day, time_t Year,
+ time_t Hours, time_t Minutes, time_t Seconds);
time_t get_date PROTO((char *date, struct timeb *now));
extern int Create_Admin PROTO ((char *dir, char *update_dir,
char *repository, char *tag, char *date,
Index: src/rcs.c
===================================================================
RCS file: /home2/cvsroot/ccvs/src/rcs.c,v
retrieving revision 1.248
diff -u -p -r1.248 rcs.c
--- src/rcs.c 7 Jun 2001 19:10:26 -0000 1.248
+++ src/rcs.c 18 Jun 2001 10:16:45 -0000
@@ -3349,27 +3349,32 @@ struct rcs_keyword
{
const char *string;
size_t len;
+ int has_arg;
};
-#define KEYWORD_INIT(s) (s), sizeof (s) - 1
+#define KEYWORD_INIT(s) (s), (sizeof (s) - 1)
static const struct rcs_keyword keywords[] =
{
- { KEYWORD_INIT ("Author") },
- { KEYWORD_INIT ("Date") },
- { KEYWORD_INIT ("Header") },
- { KEYWORD_INIT ("Id") },
- { KEYWORD_INIT ("Locker") },
- { KEYWORD_INIT ("Log") },
- { KEYWORD_INIT ("Name") },
- { KEYWORD_INIT ("RCSfile") },
- { KEYWORD_INIT ("Revision") },
- { KEYWORD_INIT ("Source") },
- { KEYWORD_INIT ("State") },
- { NULL, 0 }
+ { KEYWORD_INIT ("Author"), 0 },
+ { KEYWORD_INIT ("Date"), 0 },
+ { KEYWORD_INIT ("DateLocal"), 0 },
+ { KEYWORD_INIT ("DateZone"), 1 },
+ { KEYWORD_INIT ("Header"), 0 },
+ { KEYWORD_INIT ("Id"), 0 },
+ { KEYWORD_INIT ("Locker"), 0 },
+ { KEYWORD_INIT ("Log"), 0 },
+ { KEYWORD_INIT ("Name"), 0 },
+ { KEYWORD_INIT ("RCSfile"), 0 },
+ { KEYWORD_INIT ("Revision"), 0 },
+ { KEYWORD_INIT ("Source"), 0 },
+ { KEYWORD_INIT ("State"), 0 },
+ { NULL, 0, 0 }
};
enum keyword
{
KEYWORD_AUTHOR = 0,
KEYWORD_DATE,
+ KEYWORD_DATELOCAL,
+ KEYWORD_DATEZONE,
KEYWORD_HEADER,
KEYWORD_ID,
KEYWORD_LOCKER,
@@ -3400,6 +3405,88 @@ printable_date (rcs_date)
return xstrdup (buf);
}
+static char *
+printable_date_local (rcs_date)
+ const char *rcs_date;
+{
+ int year, mon, mday, hour, min, sec;
+ char buf[100];
+
+ (void) sscanf (rcs_date, SDATEFORM, &year, &mon, &mday, &hour, &min,
+ &sec);
+ if (year < 1900)
+ year += 1900;
+
+ {
+ time_t t;
+ struct tm gmt, local;
+ struct tm tm;
+ struct tm *ptm;
+
+ t = 0;
+ gmt = *gmtime(&t);
+ local = *localtime(&t);
+
+ memset(&tm, 0, sizeof tm);
+ tm.tm_year = year - 1900 + (local.tm_year - gmt.tm_year);
+ tm.tm_mon = mon - 1 + (local.tm_mon - gmt.tm_mon);
+ tm.tm_mday = mday + (local.tm_mday - gmt.tm_mday);
+ tm.tm_hour = hour + (local.tm_hour - gmt.tm_hour);
+ tm.tm_min = min + (local.tm_min - gmt.tm_min);
+ tm.tm_sec = sec + (local.tm_sec - gmt.tm_sec);
+ t = mktime(&tm);
+ ptm = localtime(&t);
+ if (strftime (buf, sizeof buf, "%Y/%m/%d %H:%M:%S %Z", ptm) == 0)
+ return printable_date (rcs_date);
+ }
+
+ return xstrdup (buf);
+}
+
+static char *
+printable_date_zone (rcs_date, arg)
+ const char *rcs_date;
+ const char *arg;
+{
+ int year, mon, mday, hour, min, sec;
+ time_t t;
+ struct tm *ptm;
+ char *tz_old;
+ char *tz_new;
+ char buf[100];
+
+ (void) sscanf (rcs_date, SDATEFORM, &year, &mon, &mday, &hour, &min,
+ &sec);
+ if (year < 1900)
+ year += 1900;
+
+ t = convert_date(mon, mday, year, hour, min, sec);
+
+ /* Change to the specific TimeZone */
+ tz_old = getenv("TZ");
+ tz_new = xmalloc (3 + strlen (arg) + 1);
+ sprintf (tz_new, "TZ=%s", arg);
+ putenv (tz_new);
+ tzset ();
+ ptm = localtime(&t);
+
+ if (strftime (buf, sizeof buf, "%Y/%m/%d %H:%M:%S %Z", ptm) == 0)
+ error (1, errno, "strftime failure.");
+
+ /* Restore the system TimeZone */
+ if (tz_old)
+ {
+ char *tz_reold = xmalloc (3 + strlen (tz_old) + 1);
+ sprintf (tz_reold, "TZ=%s", tz_old);
+ putenv (tz_reold);
+ }
+ else
+ unsetenv ("TZ");
+ tzset ();
+
+ return xstrdup (buf);
+}
+
/* Escape the characters in a string so that it can be included in an
RCS value. */
@@ -3534,6 +3621,8 @@ expand_keywords (rcs, ver, name, log, lo
size_t slen;
const struct rcs_keyword *keyword;
enum keyword kw;
+ char *arg = NULL;
+ int free_arg = 0;
char *value;
int free_value;
char *sub;
@@ -3574,12 +3663,37 @@ expand_keywords (rcs, ver, name, log, lo
keyword after all. */
if (*s == ':')
{
+ if (keyword->has_arg)
+ {
+ char *p;
+ assert (arg == NULL && free_arg == 0);
+ s++;
+ if (*s != ' ')
+ continue;
+ s++;
+ if (*s != '(')
+ continue;
+ s++;
+ p = s;
+ for (; s < send; s++)
+ if (*s == ')' || *s == '\n')
+ break;
+ if (s == send || *s != ')')
+ continue;
+ arg = xmalloc (s - p + 1);
+ free_arg = 1;
+ strncpy(arg, p, s - p);
+ arg[s - p] = 0;
+ }
for (; s < send; s++)
if (*s == '$' || *s == '\n')
break;
if (s == send || *s != '$')
continue;
}
+ else
+ if (keyword->has_arg)
+ continue;
/* At this point we must replace the string from SRCH to S
with the expansion of the keyword KW. */
@@ -3604,6 +3718,16 @@ expand_keywords (rcs, ver, name, log, lo
free_value = 1;
break;
+ case KEYWORD_DATELOCAL:
+ value = printable_date_local (ver->date);
+ free_value = 1;
+ break;
+
+ case KEYWORD_DATEZONE:
+ value = printable_date_zone (ver->date, arg);
+ free_value = 1;
+ break;
+
case KEYWORD_HEADER:
case KEYWORD_ID:
{
@@ -3669,6 +3793,7 @@ expand_keywords (rcs, ver, name, log, lo
}
sub = xmalloc (keyword->len
+ + (arg == NULL ? 0 : (strlen (arg)) + 3)
+ (value == NULL ? 0 : strlen (value))
+ 10);
if (expand == KFLAG_V)
@@ -3689,6 +3814,16 @@ expand_keywords (rcs, ver, name, log, lo
sub[sublen] = ':';
sub[sublen + 1] = ' ';
sublen += 2;
+ if (arg != NULL)
+ {
+ sub[sublen] = '(';
+ ++sublen;
+ strcpy (sub + sublen, arg);
+ sublen += strlen (arg);
+ sub[sublen] = ')';
+ sub[sublen + 1] = ' ';
+ sublen += 2;
+ }
}
}
if (value != NULL)
@@ -3705,6 +3840,12 @@ expand_keywords (rcs, ver, name, log, lo
if (free_value)
free (value);
+ if (free_arg)
+ {
+ free (arg);
+ arg = NULL;
+ free_arg = 0;
+ }
/* The Log keyword requires special handling. This behaviour
is taken from RCS 5.7. The special log message is what RCS