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

Christopher Wong christopher.wong at axis.com
Fri Mar 8 09:38:05 UTC 2019


>From c37fe30ee3a13c98c77a4ec2cafe0671d4173e42 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 | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 52 insertions(+), 3 deletions(-)

diff --git a/zic.c b/zic.c
index 2ebc66a..40185b2 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,19 @@ _("%s: More than one -d option specified\n"),
 					return EXIT_FAILURE;
 				}
 				break;
+			case 'k':
+				if (truncstart == ZIC_MIN) {
+					truncstart = atoi(optarg);
+					if (truncstart > ZIC_MAX)
+						truncstart = ZIC_MAX;
+				}
+				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 +1767,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 +1883,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 +1959,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