Here's a pre-release patch of ISO-8601 date conversion for all of
subversions date needs.
Please do not apply it yet - unless you want to finish it. It probably
has errors and is largely uncommented and so on.
I'm posting this here, because it would be nice for people to explore
the possible ramifications this might have on several things in the
repository. For example an old client on a new working directory will
happily segfault at the first operation - which is not so surprising.
Anyway, hope to work more on this the next few days to get it
finished.
-- Naked
Index: ./build.conf
===================================================================
--- ./build.conf
+++ ./build.conf Mon May 13 23:13:16 2002
@@ -289,6 +289,14 @@
install = test
libs = libsvn_test libsvn_subr $(SVN_APRUTIL_LIBS) $(SVN_APR_LIBS)
+# test time functions
+[time-test]
+type = exe
+path = subversion/tests/libsvn_subr
+sources = time-test.c
+install = test
+libs = libsvn_test libsvn_subr $(SVN_APRUTIL_LIBS) $(SVN_APR_LIBS)
+
# test eol conversion and keyword substitution routines
[translate-test]
type = exe
Index: ./subversion/libsvn_subr/time.c
===================================================================
--- ./subversion/libsvn_subr/time.c
+++ ./subversion/libsvn_subr/time.c Mon May 13 23:10:11 2002
@@ -29,6 +29,18 @@
/*** Code. ***/
/* Our timestamp strings look like this:
+ *
+ * "2002-05-07Thh:mm:ss.uuuuuuZ"
+ *
+ * The format is conformant with ISO-8601 and the date format required
+ * by RFC2518 for creationdate. It is a direct converision between
+ * apr_time_t and a string, so converting to string and back retains
+ * the exact value.
+ */
+static const char * const timestamp_format =
+"%04d-%02d-%02dT%02d:%02d:%02d.%06dZ";
+
+/* Our old timestamp strings looked like this:
*
* "Tue 3 Oct 2000 HH:MM:SS.UUU (day 277, dst 1, gmt_off -18000)"
*
@@ -37,12 +49,10 @@
* to completely fill in an apr_time_exp_t: tm_yday, tm_isdst,
* and tm_gmtoff.
*
- * kff todo: what about portability problems resulting from the
- * plain int assumptions below, though? Using apr_strftime() would
- * fix that, but converting the strings back is still a problem (see
- * the comment in svn_wc__time_to_string()).
+ * This format is still recognized on input, for backward
+ * compatibility, but no longer generated.
*/
-static const char * const timestamp_format =
+static const char * const old_timestamp_format =
"%s %d %s %d %02d:%02d:%02d.%06d (day %03d, dst %d, gmt_off %06d)";
@@ -58,25 +68,24 @@
furthermore their current implementations can only return success
anyway. */
- apr_time_exp_lt (&exploded_time, t);
-
- /* It would be nice to use apr_strftime(), but APR doesn't give a way
- to convert back, so we wouldn't be able to share the format string
- between the writer and reader. Sigh. Also, apr_strftime() doesn't
- offer format codes for its special tm_usec and tm_gmtoff fields. */
+ /* We get the date in GMT now -- and expect the tm_gmtoff and
+ tm_isdst to be not set. We also ignore the weekday and yearday,
+ since those are not needed. */
+
+ apr_time_exp_gmt (&exploded_time, t);
+
+ /* It would be nice to use apr_strftime(), but APR doesn't give a
+ way to convert back, so we wouldn't be able to share the format
+ string between the writer and reader. */
t_cstr = apr_psprintf (pool,
timestamp_format,
- apr_day_snames[exploded_time.tm_wday],
- exploded_time.tm_mday,
- apr_month_snames[exploded_time.tm_mon],
exploded_time.tm_year + 1900,
+ exploded_time.tm_mon + 1,
+ exploded_time.tm_mday,
exploded_time.tm_hour,
exploded_time.tm_min,
exploded_time.tm_sec,
- exploded_time.tm_usec,
- exploded_time.tm_yday + 1,
- exploded_time.tm_isdst,
- exploded_time.tm_gmtoff);
+ exploded_time.tm_usec);
return t_cstr;
}
@@ -95,30 +104,6 @@
}
-/* ### todo:
-
- Recently Branko changed svn_time_from_string (or rather, he changed
- svn_wc__string_to_time, but the function's name has changed since
- then) to use apr_implode_gmt. So now that function is using GMT,
- but its inverse above, svn_time_to_string, is using localtime.
-
- I'm not sure what the right thing to do is; see issue #404. See
- also the thread entitled "apr_implode_time and time zones" in the
- APR dev mailing list archives:
-
- http://apr.apache.org/mail/dev/200106.gz
-
- That discussion between Branko and David Reid is directly
- relevant.
-
- Note that Subversion repositories probably want to record commit
- dates in GMT. Maybe we should just make Subversion's string
- representation for times always use GMT -- that's good for
- repositories, and for working copies it doesn't really matter since
- humans don't have to read the timestamps in SVN/entries files much
- (and when they do, they can easily do the conversion). */
-
-
apr_time_t
svn_time_from_nts (const char *data)
{
@@ -126,26 +111,54 @@
char wday[4], month[4];
apr_time_t when;
- sscanf (data,
- timestamp_format,
- wday,
- &exploded_time.tm_mday,
- month,
- &exploded_time.tm_year,
- &exploded_time.tm_hour,
- &exploded_time.tm_min,
- &exploded_time.tm_sec,
- &exploded_time.tm_usec,
- &exploded_time.tm_yday,
- &exploded_time.tm_isdst,
- &exploded_time.tm_gmtoff);
-
- exploded_time.tm_year -= 1900;
- exploded_time.tm_yday -= 1;
- exploded_time.tm_wday = find_matching_string (wday, apr_day_snames);
- exploded_time.tm_mon = find_matching_string (month, apr_month_snames);
-
- apr_implode_gmt (&when, &exploded_time);
+ /* First try the new timestamp format. */
+ if (sscanf (data,
+ timestamp_format,
+ &exploded_time.tm_year,
+ &exploded_time.tm_mon,
+ &exploded_time.tm_mday,
+ &exploded_time.tm_hour,
+ &exploded_time.tm_min,
+ &exploded_time.tm_sec,
+ &exploded_time.tm_usec) == 7)
+ {
+ exploded_time.tm_year -= 1900;
+ exploded_time.tm_mon -= 1;
+ exploded_time.tm_wday = 0;
+ exploded_time.tm_yday = 0;
+ exploded_time.tm_isdst = 0;
+ exploded_time.tm_gmtoff = 0;
+
+ apr_implode_gmt (&when, &exploded_time);
+ }
+ /* Then try the compatibility option. */
+ else if (sscanf (data,
+ old_timestamp_format,
+ wday,
+ &exploded_time.tm_mday,
+ month,
+ &exploded_time.tm_year,
+ &exploded_time.tm_hour,
+ &exploded_time.tm_min,
+ &exploded_time.tm_sec,
+ &exploded_time.tm_usec,
+ &exploded_time.tm_yday,
+ &exploded_time.tm_isdst,
+ &exploded_time.tm_gmtoff) == 11)
+ {
+ exploded_time.tm_year -= 1900;
+ exploded_time.tm_yday -= 1;
+ exploded_time.tm_wday = find_matching_string (wday, apr_day_snames);
+ exploded_time.tm_mon = find_matching_string (month, apr_month_snames);
+
+ apr_implode_gmt (&when, &exploded_time);
+ }
+ /* Timestamp is something we do not recognize. */
+ else
+ {
+ /* Better zero than something random. */
+ when = 0;
+ }
return when;
}
Index: ./subversion/tests/libsvn_subr/time-test.c
===================================================================
--- ./subversion/tests/libsvn_subr/time-test.c
+++ ./subversion/tests/libsvn_subr/time-test.c Mon May 13 22:20:49 2002
@@ -0,0 +1,165 @@
+/*
+ * path-test.c -- test the path functions
+ *
+ * ====================================================================
+ * Copyright (c) 2000-2002 CollabNet. All rights reserved.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://subversion.tigris.org/license-1.html.
+ * If newer versions of this license are posted there, you may use a
+ * newer version instead, at your option.
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals. For exact contribution history, see the revision
+ * history and logs, available at http://subversion.tigris.org/.
+ * ====================================================================
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <apr_general.h>
+#include "svn_time.h"
+#include "svn_test.h"
+
+
+apr_time_t test_timestamp = APR_TIME_C(1021316450966679);
+const char *test_timestring =
+"2002-05-13T19:00:50.966679Z";
+const char *test_old_timestring =
+"Mon 13 May 2002 22:00:50.966679 (day 133, dst 1, gmt_off 010800)";
+
+
+static svn_error_t *
+test_time_to_nts (const char **msg,
+ svn_boolean_t msg_only,
+ apr_pool_t *pool)
+{
+ const char *timestring;
+
+ *msg = "test svn_time_to_nts";
+
+ if (msg_only)
+ return SVN_NO_ERROR;
+
+ timestring = svn_time_to_nts(test_timestamp,pool);
+
+ if (strcmp(timestring,test_timestring) != 0)
+ {
+ return svn_error_createf
+ (SVN_ERR_TEST_FAILED, 0, NULL, pool,
+ "svn_time_to_nts (%" APR_TIME_T_FMT
+ ") returned date string '%s' instead of '%s'",
+ test_timestamp,timestring,test_timestring);
+ }
+
+ return SVN_NO_ERROR;
+}
+
+
+static svn_error_t *
+test_time_from_nts (const char **msg,
+ svn_boolean_t msg_only,
+ apr_pool_t *pool)
+{
+ apr_time_t timestamp;
+
+ *msg = "test svn_time_from_nts";
+
+ if (msg_only)
+ return SVN_NO_ERROR;
+
+ timestamp = svn_time_from_nts(test_timestring);
+
+ if (timestamp != test_timestamp)
+ {
+ return svn_error_createf
+ (SVN_ERR_TEST_FAILED, 0, NULL, pool,
+ "svn_time_from_nts (%s) returned time '%" APR_TIME_T_FMT
+ "' instead of '%" APR_TIME_T_FMT "'",
+ test_timestring,timestamp,test_timestamp);
+ }
+
+ return SVN_NO_ERROR;
+}
+
+
+static svn_error_t *
+test_time_from_nts_old (const char **msg,
+ svn_boolean_t msg_only,
+ apr_pool_t *pool)
+{
+ apr_time_t timestamp;
+
+ *msg = "test svn_time_from_nts (old format)";
+
+ if (msg_only)
+ return SVN_NO_ERROR;
+
+ timestamp = svn_time_from_nts(test_old_timestring);
+
+ if (timestamp != test_timestamp)
+ {
+ return svn_error_createf
+ (SVN_ERR_TEST_FAILED, 0, NULL, pool,
+ "svn_time_from_nts (%s) returned time '%" APR_TIME_T_FMT
+ "' instead of '%" APR_TIME_T_FMT "'",
+ test_old_timestring,timestamp,test_timestamp);
+ }
+
+ return SVN_NO_ERROR;
+}
+
+
+static svn_error_t *
+test_time_invariant (const char **msg,
+ svn_boolean_t msg_only,
+ apr_pool_t *pool)
+{
+ apr_time_t current_timestamp = apr_time_now();
+ const char *timestring;
+ apr_time_t timestamp;
+
+ *msg = "test svn_time_to_nts and svn_time_from_nts invariant";
+
+ if (msg_only)
+ return SVN_NO_ERROR;
+
+ timestring = svn_time_to_nts(current_timestamp,pool);
+ timestamp = svn_time_from_nts(timestring);
+
+ if (timestamp != current_timestamp)
+ {
+ return svn_error_createf
+ (SVN_ERR_TEST_FAILED, 0, NULL, pool,
+ "svn_time_from_nts ( svn_time_to_nts (n) ) returned time '%" APR_TIME_T_FMT
+ "' instead of '%" APR_TIME_T_FMT "'",
+ timestamp,current_timestamp);
+ }
+
+ return SVN_NO_ERROR;
+}
+
+
+
+/* The test table. */
+
+svn_error_t * (*test_funcs[]) (const char **msg,
+ svn_boolean_t msg_only,
+ apr_pool_t *pool) = {
+ 0,
+ test_time_to_nts,
+ test_time_from_nts,
+ test_time_from_nts_old,
+ test_time_invariant,
+ 0
+};
+
+
+
+/*
+ * local variables:
+ * eval: (load-file "../../../tools/dev/svn-dev.el")
+ * end:
+ */
+
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Tue May 14 00:45:39 2002