info-cvs
[Top][All Lists]
Advanced

[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

reply via email to

[Prev in Thread] Current Thread [Next in Thread]