diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2017-07-04 12:41:29 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2017-07-04 12:41:29 +0300 |
commit | 3fc6fc8ae9fe5980abf25e109c96934cb1fdb1eb (patch) | |
tree | a8e86fd4842381fe7c470b6ce0d8806bc7c07d85 | |
parent | 55ce659fd9a9aa49de31d33f7937fb5966fb2e1d (diff) | |
download | mailutils-3fc6fc8ae9fe5980abf25e109c96934cb1fdb1eb.tar.gz mailutils-3fc6fc8ae9fe5980abf25e109c96934cb1fdb1eb.tar.bz2 |
Improve parsedate & related MH formats
* libmailutils/datetime/parsedate.y (spec production): If a non-signed
number is given, treat it as a (positive) timezone, unless tz is already
set, or as a year number, unless a year is already set, or throw an
error otherwise.
(mu_parse_date_dtl): Revert sign of the returned utc_offset
* mh/mh_format.c (builtin_tzone): Compatibility fix
* mh/tests/fmtfunc.at: Test more functions.
-rw-r--r-- | libmailutils/datetime/parsedate.y | 45 | ||||
-rw-r--r-- | mh/mh_format.c | 35 | ||||
-rw-r--r-- | mh/tests/fmtfunc.at | 49 |
3 files changed, 93 insertions, 36 deletions
diff --git a/libmailutils/datetime/parsedate.y b/libmailutils/datetime/parsedate.y index 8ea9b2c43..a422d59d2 100644 --- a/libmailutils/datetime/parsedate.y +++ b/libmailutils/datetime/parsedate.y @@ -116,7 +116,25 @@ struct pd_date #define SET_DAY(d,v) __SET_DAY(d,v,YYERROR) #define SET_MONTH(d,v) __SET_MONTH(d,v,YYERROR) #define SET_YEAR(d,v) __SET_YEAR(d,v,YYERROR) -#define SET_TZ(d,v) __SET_TZ(d,v,YYERROR) +#define SET_TZ(d,v) __SET_TZ(d,v,YYERROR) +/* Set timezone from a packed representation (HHMM) + + The proper way of doing so would be: + +#define SET_TZ_PACK(d,v) \ + SET_TZ (d, ((v) < 0 ? -(-(v) % 100 + (-(v) / 100) * 60) \ + : ((v) % 100 + ((v) / 100) * 60))) + + However, we need to invert the sign in order for mktime + to work properly (see mu_parse_date_dtl below). The proper + sign is then restored upon return from the function. + + Once mu_mktime is in place, this can be changed. +*/ +#define SET_TZ_PACK(d,v) \ + SET_TZ (d, ((v) < 0 ? (-(v) % 100 + (-(v) / 100) * 60) \ + : -((v) % 100 + ((v) / 100) * 60))) + #define SET_MERIDIAN(d,v) __SET_MERIDIAN(d,v,YYERROR) #define SET_ORDINAL(d,v) __SET_ORDINAL(d,v,YYERROR) #define SET_NUMBER(d,v) __SET_NUMBER(d,v,YYERROR) @@ -225,7 +243,19 @@ spec : /* NULL */ { if (MASK_IS_SET ($1.date.mask, (MU_PD_MASK_TIME|MU_PD_MASK_DATE)) && !$1.rel.mask) - SET_YEAR ($1.date, $2); + { + if (MASK_IS_SET ($1.date.mask, MU_PD_MASK_YEAR)) + { + if (!MASK_IS_SET ($1.date.mask, MU_PD_MASK_TZ)) + SET_TZ_PACK ($1.date, $2); + else + YYERROR; + } + else + { + SET_YEAR ($1.date, $2); + } + } else { if ($2 > 10000) @@ -277,10 +307,7 @@ time : T_UNUMBER T_MERIDIAN SET_HOUR ($$, $1); SET_MINUTE ($$, $3); SET_MERIDIAN ($$, MER24); - SET_TZ ($$, ($4 < 0 - ? -$4 % 100 + (-$4 / 100) * 60 - : - ($4 % 100 + ($4 / 100) * 60))); - + SET_TZ_PACK ($$, $4); } | T_UNUMBER ':' T_UNUMBER ':' T_UNUMBER o_merid { @@ -297,9 +324,7 @@ time : T_UNUMBER T_MERIDIAN SET_MINUTE ($$, $3); SET_SECOND ($$, $5); SET_MERIDIAN ($$, MER24); - SET_TZ ($$, ($6 < 0 - ? -$6 % 100 + (-$6 / 100) * 60 - : - ($6 % 100 + ($6 / 100) * 60))); + SET_TZ_PACK ($$, $6); } ; @@ -1153,7 +1178,7 @@ mu_parse_date_dtl (const char *p, const time_t *now, { if (MASK_TEST (pd.date.mask, MU_PD_MASK_TZ)) { - rettz->utc_offset = pd.date.tz * 60L; + rettz->utc_offset = - pd.date.tz * 60L; rettz->tz_name = pd.date.tzname ? pd.date.tzname : (tm.tm_isdst != -1 ? tzname[tm.tm_isdst] : NULL); diff --git a/mh/mh_format.c b/mh/mh_format.c index 3948be49f..1278bfa28 100644 --- a/mh/mh_format.c +++ b/mh/mh_format.c @@ -1104,29 +1104,32 @@ static void builtin_tzone (struct mh_fvm *mach) { struct mu_timezone tz; + char buf[6]; + int s; + unsigned hrs; _parse_date (mach, NULL, &tz, NULL); - + +#if 0 + /* FIXME: If symbolic tz representation is needed, we'd do: */ if (tz.tz_name) mh_string_load (&mach->str[R_REG], tz.tz_name); else - { - char buf[6]; - int s; - unsigned hrs; + /* .... */ + /* However, MH's tzone function simply formats the timezone */ +#endif - if (tz.utc_offset < 0) - { - s = '-'; - tz.utc_offset = - tz.utc_offset; - } - else - s = '+'; - hrs = tz.utc_offset / 3600; - snprintf (buf, sizeof buf, "%c%02u%02u", s, - hrs, (tz.utc_offset - hrs * 3600) / 60); - mh_string_load (&mach->str[R_REG], buf); + if (tz.utc_offset < 0) + { + s = '-'; + tz.utc_offset = - tz.utc_offset; } + else + s = '+'; + hrs = tz.utc_offset / 3600; + snprintf (buf, sizeof buf, "%c%02u%02u", s, + hrs, (tz.utc_offset - hrs * 3600) / 60); + mh_string_load (&mach->str[R_REG], buf); } /* szone date integer timezone explicit? diff --git a/mh/tests/fmtfunc.at b/mh/tests/fmtfunc.at index 8f8b81c27..07be0e07d 100644 --- a/mh/tests/fmtfunc.at +++ b/mh/tests/fmtfunc.at @@ -464,7 +464,17 @@ FMTFUNC([weekday], [Monday ]) -# FIXME: sday +FMTFUNC([sday], +[%(sday{Date}) +%(sday{X-Date}) +], +[Date: Mon, 3 Jul 2017 13:17:58 +0300 +X-Date: 3 Jul 2017 13:17:58 +0300 + +], +[1 +0 +]) FMTFUNC([mday], [%(mday{Date}) @@ -522,17 +532,36 @@ FMTFUNC([year], # FIXME: zone -# FIXME: This returns EEST if tz files are properly set -# FMTFUNC([tzone], -# [%(tzone{Date}) -# ], -# [Date: Mon, 3 Jul 2017 13:17:58 +0300 +FMTFUNC([tzone], +[%(tzone{Date}) +%(tzone{X-Date-1}) +%(tzone{X-Date-2}) +%(tzone{X-Date-3}) +], +[Date: Mon, 3 Jul 2017 13:17:58 +0300 +X-Date-1: Mon, 3 Jul 2017 13:17:58 -0500 +X-Date-2: Mon, 3 Jul 2017 13:17:58 +0000 +X-Date-3: Mon, 3 Jul 2017 13:17:58 0000 -# ], -# [+0300 -# ]) -# FIXME: szone +], +[+0300 +-0500 ++0000 ++0000 +]) + +FMTFUNC([szone], +[%(szone{Date}) +%(szone{X-Date}) +], +[Date: Mon, 3 Jul 2017 13:17:58 +0300 +X-Date: Mon, 3 Jul 2017 13:17:58 + +], +[1 +0 +]) # FIXME: date2local |