Options for ZicDump, typically specified on the command line.
Example #1
0
 private static void ProcessDirectory(string directory, Options options, TextWriter writer)
 {
     var pairs = Directory.EnumerateFiles(directory, "*", SearchOption.AllDirectories)
         .Select(file => new
         {
             file,
             id = file.StartsWith(directory) ?
                 file.Substring(directory.Length).Replace("\\", "/").TrimStart('/') : file
         })
         .Where(pair => pair.id != "zone.tab")
         .OrderBy(pair => pair.id, StringComparer.Ordinal)
         .ToList();
     if (options.ZoneId != null)
     {
         var pair = pairs.FirstOrDefault(p => p.id == options.ZoneId);
         if (pair == null)
         {
             throw new Exception($"Unknown zone ID: {options.ZoneId}");
         }
         ProcessFile(pair.id, pair.file, options, writer);
     }
     else
     {
         foreach (var pair in pairs)
         {
             ProcessFile(pair.id, pair.file, options, writer);
         }
     }
 }
Example #2
0
        static int Main(string[] args)
        {
            Options options = new Options();
            ICommandLineParser parser = new CommandLineParser(new CommandLineParserSettings(Console.Error) { MutuallyExclusive = true });
            if (!parser.ParseArguments(args, options))
            {
                return 1;
            }

            using (var output = options.OutputFile == null ? Console.Out : File.CreateText(options.OutputFile))
            {
                var file = options.Source;
                if (File.Exists(file))
                {
                    ProcessFile(file, file, options, output);
                }
                else if (Directory.Exists(file))
                {
                    var writer = new StringWriter();
                    ProcessDirectory(file, options, writer);
                    var text = writer.ToString();
                    WriteHeaders(text, options, output);
                    output.Write(text);
                }
                else
                {
                    Console.Error.WriteLine($"File not found: {file}");
                    return 1;
                }
            }
            return 0;
        }
Example #3
0
 private static void ProcessFile(string id, string file, Options options, TextWriter writer)
 {
     writer.Write($"{id}\n");
     using (var stream = File.OpenRead(file))
     {
         var zone = ZoneFile.FromStream(stream);
         var transitions = zone.GetTransitions(options);
         foreach (var transition in transitions)
         {
             writer.Write($"{transition}\n");
         }
     }
     writer.Write("\n");
 }
Example #4
0
 private static void WriteHeaders(string text, Options options, TextWriter writer)
 {
     if (options.Version != null)
     {
         writer.Write($"Version: {options.Version}\n");
     }
     using (var hashAlgorithm = SHA256.Create())
     {
         var bytes = Encoding.UTF8.GetBytes(text);
         var hash = hashAlgorithm.ComputeHash(bytes);
         var hashText = BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant();
         writer.Write($"Body-SHA-256: {hashText}\n");
     }
     writer.Write("Format: tzvalidate-0.1\n");
     writer.Write($"Range: {options.FromYear ?? 1}-{options.ToYear}\n");
     writer.Write($"Generator: {typeof(Program).GetTypeInfo().Assembly.GetName().Name}\n");
     writer.Write($"GeneratorUrl: https://github.com/nodatime/tzvalidate\n");
     writer.Write("\n");
 }
Example #5
0
        internal IEnumerable<Transition> GetTransitions(Options options)
        {
            if (transitionTypes.Length == 0)
            {
                throw new Exception("No transition types, so unable to get any data at all");
            }
            var lowerBound = (long) (DateTimeOffset.MinValue - UnixEpoch).TotalSeconds;
            var transitions = transitionTimestamps.Zip(transitionTypeIndexes,
                (tt, tti) => new
                {
                    timestamp = tt < lowerBound ? (DateTimeOffset?) null : UnixEpoch.AddSeconds(tt),
                    type = transitionTypes[tti]
                })
                .Select(pair => new Transition(pair.timestamp, TimeSpan.FromSeconds(pair.type.Offset), pair.type.IsDst, pair.type.Abbreviation))
                .ToList();
            if (options.FakeInitialTransition && transitions.Count > 0 && transitions[0].Instant != null)
            {
                // Note: in some very odd cases (e.g. tzdata94f, MET) the first transition is into standard time.
                // We'll still add one for the big bang here, and let the next part de-dupe.

                // Work out the initial type according to the localtime man page:
                // - First standard type (by transition type array) if there are any
                // - First type if not
                var initialType = transitionTypes.FirstOrDefault(t => !t.IsDst) ?? transitionTypes[0];
                transitions.Insert(0, new Transition(null, TimeSpan.FromSeconds(initialType.Offset), initialType.IsDst, initialType.Abbreviation));
            }
            Transition previousTransition = null;
            foreach (var transition in transitions)
            {
                // There may be types which only differ in ways we don't care about, e.g. whether
                // the transition is specified as wall, standard or UTC.
                if (previousTransition?.Abbreviation == transition.Abbreviation &&
                    previousTransition.Offset == transition.Offset &&
                    previousTransition.IsDaylight == transition.IsDaylight)
                {
                    continue;
                }
                previousTransition = transition;

                if (transition.Instant != null)
                {
                    var year = transition.Instant.Value.Year;
                    if (options.FromYear != null && year < options.FromYear.Value)
                    {
                        continue;
                    }
                    if (year >= options.ToYear)
                    {
                        yield break;
                    }
                }

                yield return transition;
            }
        }