From 142e33869c4c04338e6071e011b3053a28ea9173 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Mon, 16 Jul 2012 23:36:30 -0700 Subject: [PATCH] format: Make fmt_date_template() human-friendly, respect field width. The strings that fmt_date_template() returned were almost but not quite the kind of strings that humans expect to see. For one, they always used "yy", even though the code uses 4-digit years ("yyyy") when the field width is sufficient. Similarly, they never included seconds (i.e. omitted ":SS"). Finally, FMT_MOYR had an "X" where one would expect a space. This commit corrects all of the above issues. Future commits will make more use of fmt_date_template(). --- src/data/data-in.c | 14 +++++---- src/data/data-out.c | 17 +++++------ src/data/format.c | 73 +++++++++++++++++++++++++++++++++++---------- src/data/format.h | 2 +- 4 files changed, 75 insertions(+), 31 deletions(-) diff --git a/src/data/data-in.c b/src/data/data-in.c index e72d1b6ad4..14a24fffe2 100644 --- a/src/data/data-in.c +++ b/src/data/data-in.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 1997-9, 2000, 2006, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1997-9, 2000, 2006, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -1123,7 +1123,7 @@ parse_date (struct data_in *i) double time = 0, date = 0; enum time_sign time_sign = SIGN_NO_TIME; - const char *template = fmt_date_template (i->format); + const char *template = fmt_date_template (i->format, 0); size_t template_width = strlen (template); char *error; @@ -1180,14 +1180,18 @@ parse_date (struct data_in *i) case '-': case '/': case '.': - case 'X': error = parse_date_delimiter (i); break; case ':': error = parse_time_delimiter (i); case ' ': - parse_spaces (i); - error = NULL; + if (i->format != FMT_MOYR) + { + parse_spaces (i); + error = NULL; + } + else + error = parse_date_delimiter (i); break; default: assert (count == 1); diff --git a/src/data/data-out.c b/src/data/data-out.c index df447a6a12..2a0dd0a195 100644 --- a/src/data/data-out.c +++ b/src/data/data-out.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 1997-9, 2000, 2006, 2009, 2011 Free Software Foundation, Inc. + Copyright (C) 1997-9, 2000, 2006, 2009, 2011, 2012 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -387,14 +387,11 @@ output_date (const union value *input, const struct fmt_spec *format, double number = input->f; int year, month, day, yday; - const char *template = fmt_date_template (format->type); - size_t template_width = strlen (template); - int excess_width = format->w - template_width; + const char *template = fmt_date_template (format->type, format->w); char tmp[64]; char *p = tmp; - assert (format->w >= template_width); if (number == SYSMIS) goto missing; @@ -411,6 +408,8 @@ output_date (const union value *input, const struct fmt_spec *format, while (*template != '\0') { + int excess_width; + int ch = *template; int count = 1; while (template[count] == ch) @@ -439,7 +438,7 @@ output_date (const union value *input, const struct fmt_spec *format, } break; case 'y': - if (count >= 4 || excess_width >= 2) + if (count >= 4) { if (year <= 9999) p += sprintf (p, "%04d", year); @@ -499,10 +498,7 @@ output_date (const union value *input, const struct fmt_spec *format, } p += strlen (p); } - break; - case 'X': - *p++ = ' '; - break; + goto done; default: assert (count == 1); *p++ = ch; @@ -510,6 +506,7 @@ output_date (const union value *input, const struct fmt_spec *format, } } + done: buf_copy_lpad (output, format->w, tmp, p - tmp, ' '); output[format->w] = '\0'; return; diff --git a/src/data/format.c b/src/data/format.c index dc546af845..58e16d3075 100644 --- a/src/data/format.c +++ b/src/data/format.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 1997-9, 2000, 2006, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1997-9, 2000, 2006, 2010, 2011, 2012 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -881,38 +881,81 @@ fmt_usable_for_input (enum fmt_type type) return fmt_get_category (type) != FMT_CAT_CUSTOM; } -/* For time and date formats, returns a template used for input - and output. */ +/* For time and date formats, returns a template used for input and output in a + field of the given WIDTH. + + WIDTH only affects whether a 2-digit year or a 4-digit year is used, that + is, whether the returned string contains "yy" or "yyyy", and whether seconds + are include, that is, whether the returned string contains ":SS". A caller + that doesn't care whether the returned string contains "yy" or "yyyy" or + ":SS" can just specify 0 to omit them. */ const char * -fmt_date_template (enum fmt_type type) +fmt_date_template (enum fmt_type type, int width) { + const char *s1, *s2; + switch (type) { case FMT_DATE: - return "dd-mmm-yy"; + s1 = "dd-mmm-yy"; + s2 = "dd-mmm-yyyy"; + break; + case FMT_ADATE: - return "mm/dd/yy"; + s1 = "mm/dd/yy"; + s2 = "mm/dd/yyyy"; + break; + case FMT_EDATE: - return "dd.mm.yy"; + s1 = "dd.mm.yy"; + s2 = "dd.mm.yyyy"; + break; + case FMT_JDATE: - return "yyddd"; + s1 = "yyddd"; + s2 = "yyyyddd"; + break; + case FMT_SDATE: - return "yy/mm/dd"; + s1 = "yy/mm/dd"; + s2 = "yyyy/mm/dd"; + break; + case FMT_QYR: - return "q Q yy"; + s1 = "q Q yy"; + s2 = "q Q yyyy"; + break; + case FMT_MOYR: - return "mmmXyy"; + s1 = "mmm yy"; + s2 = "mmm yyyy"; + break; + case FMT_WKYR: - return "ww WK yy"; + s1 = "ww WK yy"; + s2 = "ww WK yyyy"; + break; + case FMT_DATETIME: - return "dd-mmm-yyyy HH:MM"; + s1 = "dd-mmm-yyyy HH:MM"; + s2 = "dd-mmm-yyyy HH:MM:SS"; + break; + case FMT_TIME: - return "H:MM"; + s1 = "H:MM"; + s2 = "H:MM:SS"; + break; + case FMT_DTIME: - return "D HH:MM"; + s1 = "D HH:MM"; + s2 = "D HH:MM:SS"; + break; + default: NOT_REACHED (); } + + return width >= strlen (s2) ? s2 : s1; } /* Returns a string representing the format TYPE for use in a GUI dialog. */ diff --git a/src/data/format.h b/src/data/format.h index 1744becccc..def3cdc3f7 100644 --- a/src/data/format.h +++ b/src/data/format.h @@ -134,7 +134,7 @@ bool fmt_usable_for_input (enum fmt_type) PURE_FUNCTION; int fmt_to_io (enum fmt_type) PURE_FUNCTION; bool fmt_from_io (int io, enum fmt_type *); -const char *fmt_date_template (enum fmt_type) PURE_FUNCTION; +const char *fmt_date_template (enum fmt_type, int width) PURE_FUNCTION; const char *fmt_gui_name (enum fmt_type); /* Format settings. -- 2.30.2