[tz] [PROPOSED] zic option for including data from a certain year onward

Christopher Wong christopher.wong at axis.com
Fri Mar 8 15:01:05 UTC 2019


>From 326a7b1078f62e7f0daf3a54b30a58474d22103a Mon Sep 17 00:00:00 2001
From: Christopher Wong <christwo at axis.com>
Date: Tue, 5 Feb 2019 15:02:57 +0100
Subject: [PATCH] zic.c: Add -k option to truncate with specified start time

The -k option will take a start time in seconds since
January 1, 1970 (Unix Epoch) as input. It will strip away
historical transition data before the specified start time.
The TZif files will be truncated.
---
 zic.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 49 insertions(+), 3 deletions(-)

diff --git a/zic.c b/zic.c
index 2ebc66a..ea5164f 100644
--- a/zic.c
+++ b/zic.c
@@ -610,6 +610,10 @@ static const char *	leapsec;
 static const char *	tzdefault;
 static const char *	yitcommand;
 
+/* This is used to truncate tzfiles. Only transitions starting with truncstart
+   and onward will be kept. */
+static zic_t truncstart;
+
 int
 main(int argc, char **argv)
 {
@@ -640,7 +644,8 @@ main(int argc, char **argv)
 		} else if (strcmp(argv[k], "--help") == 0) {
 			usage(stdout, EXIT_SUCCESS);
 		}
-	while ((c = getopt(argc, argv, "d:l:L:p:st:vy:")) != EOF && c != -1)
+	truncstart = ZIC_MIN;
+	while ((c = getopt(argc, argv, "d:k:l:L:p:st:vy:")) != EOF && c != -1)
 		switch (c) {
 			default:
 				usage(stderr, EXIT_FAILURE);
@@ -654,6 +659,16 @@ _("%s: More than one -d option specified\n"),
 					return EXIT_FAILURE;
 				}
 				break;
+			case 'k':
+				if (truncstart == ZIC_MIN)
+					truncstart = atol(optarg);
+				else {
+					fprintf(stderr,
+_("%s: More than one -k option specified\n"),
+						progname);
+					return EXIT_FAILURE;
+				}
+				break;
 			case 'l':
 				if (lcltime == NULL)
 					lcltime = optarg;
@@ -1749,7 +1764,7 @@ writezone(const char *const name, const char *const string, char version,
 	register FILE *			fp;
 	register ptrdiff_t		i, j;
 	register int			leapcnt32, leapi32;
-	register ptrdiff_t		timecnt32, timei32;
+	register ptrdiff_t		timecnt32, timei32, timei;
 	register int			pass;
 	static const struct tzhead	tzh0;
 	static struct tzhead		tzh;
@@ -1865,6 +1880,37 @@ writezone(const char *const name, const char *const string, char version,
 		--leapcnt32;
 		++leapi32;
 	}
+
+	timei = 0;
+	if (truncstart != ZIC_MIN) {
+		/* Discard transitions that happened before the truncstart. */
+		int nbr_removes;
+
+		nbr_removes = 0;
+		for (i = timei32; i < timecnt; ++i)
+			if (ats[i] < truncstart)
+				++nbr_removes;
+		timecnt32 -= nbr_removes;
+		timei32 += nbr_removes;
+
+		nbr_removes = 0;
+		for (i = 0; i < timecnt; ++i)
+			if (ats[i] < truncstart)
+				++nbr_removes;
+
+		if (nbr_removes > 0) {
+			/* Override the last removed transition time with the first transition
+			   time that is the start point of the truncation range. Set defaulttype
+			   to this first transition time. */
+			--nbr_removes;
+			ats[nbr_removes] = truncstart;
+			defaulttype = types[nbr_removes];
+		}
+
+		timecnt -= nbr_removes;
+		timei += nbr_removes;
+	}
+
 	/*
 	** Remove old file, if any, to snap links.
 	*/
@@ -1910,7 +1956,7 @@ writezone(const char *const name, const char *const string, char version,
 			thisleapi = leapi32;
 			thisleapcnt = leapcnt32;
 		} else {
-			thistimei = 0;
+			thistimei = timei;
 			thistimecnt = timecnt;
 			toomanytimes = thistimecnt >> 31 >> 31 >> 2 != 0;
 			thisleapi = 0;
-- 
2.11.0



More information about the tz mailing list