[gnumeric] Number match: support ISO 8602 date/time UTC values.
- From: Morten Welinder <mortenw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnumeric] Number match: support ISO 8602 date/time UTC values.
- Date: Thu, 3 Jan 2019 19:37:50 +0000 (UTC)
commit c1dd1b23e33c80d25c5439a963f76cb2c4f7ef38
Author: Morten Welinder <terra gnome org>
Date: Thu Jan 3 14:36:26 2019 -0500
Number match: support ISO 8602 date/time UTC values.
This is not meant to be perfect support, but to catch the saner 99% of
the possible strings.
NEWS | 1 +
src/number-match.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++--------
2 files changed, 53 insertions(+), 9 deletions(-)
---
diff --git a/NEWS b/NEWS
index 02d03f562..1e7957ac5 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,7 @@ Gnumeric 1.12.45
Morten:
* Add DIGAMMA function.
+ * Support ISO-8601 UTC date/time input. Mostly. [#371]
--------------------------------------------------------------------------
Gnumeric 1.12.44
diff --git a/src/number-match.c b/src/number-match.c
index f0cf15b19..193d0389d 100644
--- a/src/number-match.c
+++ b/src/number-match.c
@@ -108,6 +108,7 @@ static struct {
GORegexp re_ddMMMMyyyy;
GORegexp re_yyyymmdd1;
GORegexp re_yyyymmdd2;
+ GORegexp re_yyyymmdd3;
GORegexp re_mmddyyyy;
GORegexp re_mmdd;
GORegexp re_hhmmss1;
@@ -125,6 +126,7 @@ datetime_locale_clear (void)
go_regfree (&datetime_locale.re_ddMMMMyyyy);
go_regfree (&datetime_locale.re_yyyymmdd1);
go_regfree (&datetime_locale.re_yyyymmdd2);
+ go_regfree (&datetime_locale.re_yyyymmdd3);
go_regfree (&datetime_locale.re_mmddyyyy);
go_regfree (&datetime_locale.re_mmdd);
go_regfree (&datetime_locale.re_hhmmss1);
@@ -241,11 +243,24 @@ datetime_locale_setup (char const *lc_time)
datetime_locale_setup1 (&datetime_locale.re_yyyymmdd1, s);
g_free (s);
+ /*
+ * ISO 8601 UTC date+time (date + "T" + time + "Z")
+ * Date: "2000-12-31" or without dashes.
+ * Time: "12:34:56.123" or without colons or with fewer parts.
+ */
+ s = g_strconcat ("^(\\d\\d\\d\\d)(-?)(\\d\\d)\\2(\\d\\d)T"
+ "\\d+(:?)\\d+(\\5\\d+(",
+ p_decimal->str,
+ "\\d*)?)?(Z)\\s*$",
+ NULL);
+ datetime_locale_setup1 (&datetime_locale.re_yyyymmdd2, s);
+ g_free (s);
+
/*
* "1900/01/01"
* "1900-1-1"
*/
- datetime_locale_setup1 (&datetime_locale.re_yyyymmdd2,
+ datetime_locale_setup1 (&datetime_locale.re_yyyymmdd3,
"^(\\d\\d\\d\\d)[-/.](\\d+)[-/.](\\d+)\\b");
/*
@@ -653,6 +668,8 @@ format_match_datetime (char const *text,
char *date_format = NULL;
GnmValue *res = NULL;
char *time_format = NULL;
+ int timeend = 0;
+ const char *format_sep = " ";
if (lc_time != datetime_locale.lc_time &&
(lc_time == NULL ||
@@ -722,10 +739,27 @@ format_match_datetime (char const *text,
}
}
+ // ^(\d\d\d\d)(-?)(\d\d)\2(\d\d)T\d+(:?)\d+(\5\d+(.\d*)?)?(Z)\s*$
+ // 1 2 3 4 5 6 7 8
+ if (dig1 > 0 && /* Exclude zero. */
+ go_regexec (&datetime_locale.re_yyyymmdd2, text, G_N_ELEMENTS (match), match, 0) == 0) {
+ year = handle_year (text, match + 1);
+ month = handle_month (text, match + 3);
+ day = handle_day (text, match + 4);
+ if (valid_dmy (day, month, year)) {
+ date_format = g_strdup ("yyyy-mm-dd");
+ time_format = g_strdup ("hh:mm:ss\"Z\"");
+ format_sep = "\"T\"";
+ text += match[4].rm_eo + 1;
+ timeend = match[8].rm_so - (match[4].rm_eo + 1);
+ goto got_date;
+ }
+ }
+
/* ^(\d\d\d\d)[-/.](\d\d)[-/.](\d\d)\b */
/* 1 2 3 */
if (dig1 > 0 && /* Exclude zero. */
- go_regexec (&datetime_locale.re_yyyymmdd2, text, G_N_ELEMENTS (match), match, 0) == 0) {
+ go_regexec (&datetime_locale.re_yyyymmdd3, text, G_N_ELEMENTS (match), match, 0) == 0) {
year = handle_year (text, match + 1);
month = handle_month (text, match + 2);
day = handle_day (text, match + 3);
@@ -809,15 +843,24 @@ format_match_datetime (char const *text,
SKIP_SPACES (text);
if (*text) {
- GnmValue *v = format_match_time (text, FALSE,
- TRUE, add_format);
- GOFormat const *fmt;
+ GnmValue *v;
+ const char *subtext = text;
+ char *textcopy = NULL;
+
+ if (timeend)
+ subtext = textcopy = g_strndup (text, timeend);
+
+ v = format_match_time (subtext, FALSE,
+ TRUE, add_format);
+ g_free (textcopy);
if (!v)
goto out;
time_val = value_get_as_float (v);
- fmt = VALUE_FMT (v);
- if (fmt)
- time_format = g_strdup (go_format_as_XL (fmt));
+ if (!time_format) {
+ GOFormat const *fmt = VALUE_FMT (v);
+ if (fmt)
+ time_format = g_strdup (go_format_as_XL (fmt));
+ }
value_release (v);
} else
time_val = 0;
@@ -827,7 +870,7 @@ format_match_datetime (char const *text,
GOFormat *fmt;
if (time_format) {
char *format = g_strconcat (date_format,
- " ",
+ format_sep,
time_format,
NULL);
fmt = go_format_new_from_XL (format);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]