[tz] [PATCH] Add -R option to zic
Paul Eggert
eggert at cs.ucla.edu
Tue Jul 12 13:20:41 UTC 2022
(Need suggested by Almaz Mingaleev.)
* NEWS, zic.8: Document option.
* zic.c (usage): Mention new option.
(redundant_time): New static var.
(redundant_time_option): New function.
(main, writezone, outzone): Support -R.
---
NEWS | 4 ++++
zic.8 | 11 +++++++++++
zic.c | 44 +++++++++++++++++++++++++++++++++++++++++---
3 files changed, 56 insertions(+), 3 deletions(-)
diff --git a/NEWS b/NEWS
index 60deee4..850e38b 100644
--- a/NEWS
+++ b/NEWS
@@ -5,6 +5,7 @@ Unreleased, experimental changes
Briefly:
Iran no longer observes DST after 2022.
Rename Europe/Kiev to Europe/Kyiv.
+ New zic -R option
Changes to future timestamps
@@ -38,6 +39,9 @@ Unreleased, experimental changes
Changes to code
+ zic has a new option '-R @N' to output explicit transitions < N.
+ (Need suggested by Almaz Mingaleev.)
+
'zic -r @N' no longer outputs bad data when N < first transition.
(Problem introduced in 2021d and reported by Peter Krefting.)
diff --git a/zic.8 b/zic.8
index 3f228a6..0cd0781 100644
--- a/zic.8
+++ b/zic.8
@@ -159,6 +159,17 @@ Also see the
.B "\*-b slim"
option for another way to shrink output size.
.TP
+.BI "\*-R @" hi
+Generate redundant trailing explicit transitions for timestamps
+that occur less than
+.I hi
+seconds since the Epoch, even though the transitions could be
+more concisely represented via the extended POSIX TZ string.
+This option does not affect the represented timestamps.
+Although it accommodates nonstandard TZif readers
+that ignore the extended POSIX TZ string,
+it increases the size of the altered output files.
+.TP
.BI "\*-t " file
When creating local time information, put the configuration link in
the named file rather than in the standard location.
diff --git a/zic.c b/zic.c
index 19e145a..e081c3d 100644
--- a/zic.c
+++ b/zic.c
@@ -579,7 +579,8 @@ usage(FILE *stream, int status)
_("%s: usage is %s [ --version ] [ --help ] [ -v ] \\\n"
"\t[ -b {slim|fat} ] [ -d directory ] [ -l localtime ]"
" [ -L leapseconds ] \\\n"
- "\t[ -p posixrules ] [ -r '[@lo][/@hi]' ] [ -t localtime-link ] \\\n"
+ "\t[ -p posixrules ] [ -r '[@lo][/@hi]' ] [ -R '@hi' ] \\\n"
+ "\t[ -t localtime-link ] \\\n"
"\t[ filename ... ]\n\n"
"Report bugs to %s.\n"),
progname, progname, REPORT_BUGS_TO);
@@ -681,6 +682,9 @@ static zic_t const max_time = MAXVAL(zic_t, TIME_T_BITS_IN_FILE);
static zic_t lo_time = MINVAL(zic_t, TIME_T_BITS_IN_FILE);
static zic_t hi_time = MAXVAL(zic_t, TIME_T_BITS_IN_FILE);
+/* The time specified by the -R option, defaulting to MIN_TIME. */
+static zic_t redundant_time = MINVAL(zic_t, TIME_T_BITS_IN_FILE);
+
/* The time specified by an Expires line, or negative if no such line. */
static zic_t leapexpires = -1;
@@ -712,6 +716,22 @@ timerange_option(char *timerange)
return true;
}
+/* Generate redundant time stamps up to OPT. Return true if successful. */
+static bool
+redundant_time_option(char *opt)
+{
+ if (*opt == '@') {
+ intmax_t redundant;
+ char *opt_end;
+ redundant = strtoimax(opt + 1, &opt_end, 10);
+ if (opt_end != opt + 1 && !*opt_end) {
+ redundant_time = max(redundant_time, redundant);
+ return true;
+ }
+ }
+ return false;
+}
+
static const char * psxrules;
static const char * lcltime;
static const char * directory;
@@ -764,7 +784,8 @@ main(int argc, char **argv)
} else if (strcmp(argv[k], "--help") == 0) {
usage(stdout, EXIT_SUCCESS);
}
- while ((c = getopt(argc, argv, "b:d:l:L:p:r:st:vy:")) != EOF && c != -1)
+ while ((c = getopt(argc, argv, "b:d:l:L:p:r:R:st:vy:")) != EOF
+ && c != -1)
switch (c) {
default:
usage(stderr, EXIT_FAILURE);
@@ -851,12 +872,23 @@ _("%s: invalid time range: %s\n"),
}
timerange_given = true;
break;
+ case 'R':
+ if (! redundant_time_option(optarg)) {
+ fprintf(stderr, _("%s: invalid time: %s\n"),
+ progname, optarg);
+ return EXIT_FAILURE;
+ }
+ break;
case 's':
warning(_("-s ignored"));
break;
}
if (optind == argc - 1 && strcmp(argv[optind], "=") == 0)
usage(stderr, EXIT_FAILURE); /* usage message by request */
+ if (hi_time + (hi_time < ZIC_MAX) < redundant_time) {
+ fprintf(stderr, _("%s: -R time exceeds -r cutoff\n"), progname);
+ return EXIT_FAILURE;
+ }
if (bloat == 0) {
static char const bloat_default[] = ZIC_BLOAT_DEFAULT;
if (strcmp(bloat_default, "slim") == 0)
@@ -2139,7 +2171,10 @@ writezone(const char *const name, const char *const string, char version,
rangeall.defaulttype = defaulttype;
rangeall.count = timecnt;
rangeall.leapcount = leapcnt;
- range64 = limitrange(rangeall, lo_time, hi_time, ats, types);
+ range64 = limitrange(rangeall, lo_time,
+ max(hi_time,
+ redundant_time - (ZIC_MIN < redundant_time)),
+ ats, types);
range32 = limitrange(range64, INT32_MIN, INT32_MAX, ats, types);
/* TZif version 4 is needed if a no-op transition is appended to
@@ -2893,6 +2928,8 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
max_year = min_year + years_of_observations;
}
}
+ max_year = max(max_year, (redundant_time / (SECSPERDAY * DAYSPERNYEAR)
+ + EPOCH_YEAR + 1));
max_year0 = max_year;
if (want_bloat()) {
/* For the benefit of older systems,
@@ -3061,6 +3098,7 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
offset = oadd(zp->z_stdoff, rp->r_save);
if (!want_bloat() && !useuntil && !do_extend
&& prevrp && lo_time <= prevktime
+ && redundant_time <= ktime
&& rp->r_hiyear == ZIC_MAX
&& prevrp->r_hiyear == ZIC_MAX)
break;
--
2.34.1
More information about the tz
mailing list