Beispiel #1
0
        private void LoadLocationFiles(FileSource source, TzdbDatabase database)
        {
            if (!source.Contains(Iso3166TabFile))
            {
                return;
            }
            var iso3166 = source.ReadLines(Iso3166TabFile)
                          .Where(line => line != "" && !line.StartsWith("#"))
                          .Select(line => line.Split('\t'))
                          .ToList();

            if (source.Contains(ZoneTabFile))
            {
                var iso3166Dict = iso3166.ToDictionary(bits => bits[0], bits => bits[1]);
                database.ZoneLocations = source.ReadLines(ZoneTabFile)
                                         .Where(line => line != "" && !line.StartsWith("#"))
                                         .Select(line => TzdbZoneLocationParser.ParseLocation(line, iso3166Dict))
                                         .ToList();
            }
            if (source.Contains(Zone1970TabFile))
            {
                var iso3166Dict = iso3166.ToDictionary(bits => bits[0], bits => new TzdbZone1970Location.Country(code: bits[0], name: bits[1]));
                database.Zone1970Locations = source.ReadLines(Zone1970TabFile)
                                             .Where(line => line != "" && !line.StartsWith("#"))
                                             .Select(line => TzdbZoneLocationParser.ParseEnhancedLocation(line, iso3166Dict))
                                             .ToList();
            }
        }
 private void LoadLocationFiles(FileSource source, TzdbDatabase database)
 {
     if (!source.Contains(Iso3166TabFile))
     {
         return;
     }
     var iso3166 = source.ReadLines(Iso3166TabFile)
           .Where(line => line != "" && !line.StartsWith("#"))
           .Select(line => line.Split('\t'))
           .ToList();
     if (source.Contains(ZoneTabFile))
     {
         var iso3166Dict = iso3166.ToDictionary(bits => bits[0], bits => bits[1]);
         database.ZoneLocations = source.ReadLines(ZoneTabFile)
            .Where(line => line != "" && !line.StartsWith("#"))
            .Select(line => TzdbZoneLocationParser.ParseLocation(line, iso3166Dict))
            .ToList();
     }
     if (source.Contains(Zone1970TabFile))
     {
         var iso3166Dict = iso3166.ToDictionary(bits => bits[0], bits => new TzdbZone1970Location.Country(code: bits[0], name: bits[1]));
         database.Zone1970Locations = source.ReadLines(ZoneTabFile)
            .Where(line => line != "" && !line.StartsWith("#"))
            .Select(line => TzdbZoneLocationParser.ParseEnhancedLocation(line, iso3166Dict))
            .ToList();
     }
 }
 /// <summary>
 ///   Parses the file defined by the given <see cref="FileInfo" />.
 /// </summary>
 /// <remarks>
 ///   Currently this compiler only handles files in the Olson (TZDB) zone info format.
 /// </remarks>
 /// <param name="file">The file to parse.</param>
 /// <param name="database">The <see cref="TzdbDatabase" /> where the parsed data is placed.</param>
 internal void ParseFile(FileInfo file, TzdbDatabase database)
 {
     using (FileStream stream = file.OpenRead())
     {
         tzdbParser.Parse(stream, database);
     }
 }
Beispiel #4
0
        public void Write(TzdbDatabase database, WindowsZones cldrWindowsZones)
        {
            var timeZoneMap = new Dictionary <string, string>();

            foreach (var zone in database.GenerateDateTimeZones())
            {
                timeZoneMap.Add(zone.Id, zone.Id);
                WriteTimeZone(zone);
            }

            // Normalize the aliases
            foreach (var key in database.Aliases.Keys)
            {
                var value = database.Aliases[key];
                while (database.Aliases.ContainsKey(value))
                {
                    value = database.Aliases[value];
                }
                timeZoneMap.Add(key, value);
            }
            resourceWriter.AddResource(TzdbResourceData.VersionKey, database.Version);
            WriteDictionary(TzdbResourceData.IdMapKey, timeZoneMap);
            WriteDictionary(TzdbResourceData.WindowsToPosixMapKey, cldrWindowsZones.PrimaryMapping);
            resourceWriter.AddResource(TzdbResourceData.WindowsToPosixMapVersionKey, cldrWindowsZones.Version);
            resourceWriter.Close();
        }
 /// <summary>
 /// Parses all of the given files.
 /// </summary>
 /// <param name="files">The <see cref="IEnumerable{T}" /> of <see cref="FileInfo" /> objects.</param>
 /// <param name="database">The <see cref="TzdbDatabase" /> where the parsed data is placed.</param>
 private void ParseAllFiles(IEnumerable <FileInfo> files, TzdbDatabase database)
 {
     foreach (var file in files)
     {
         Console.WriteLine("Parsing file {0} . . .", file.Name);
         ParseFile(file, database);
     }
 }
 /// <summary>
 /// Parses all of the given files.
 /// </summary>
 /// <param name="files">The <see cref="IEnumerable{T}" /> of <see cref="FileInfo" /> objects.</param>
 /// <param name="database">The <see cref="TzdbDatabase" /> where the parsed data is placed.</param>
 private void ParseAllFiles(IEnumerable<FileInfo> files, TzdbDatabase database)
 {
     foreach (var file in files)
     {
         Console.WriteLine("Parsing file {0} . . .", file.Name);
         ParseFile(file, database);
     }
 }
 /// <summary>
 /// Tries to compile the contents of a path to a TzdbDatabase. The path can be a directory
 /// name containing the TZDB files, or a local tar.gz file, or a remote tar.gz file.
 /// The version ID is taken from the Makefile, if it exists. Otherwise, an attempt is made to guess
 /// it based on the last element of the path, to match a regex of \d{2,4}[a-z] (anywhere within the element).
 /// </summary>
 public TzdbDatabase Compile(string path)
 {
     var source = LoadSource(path);
     var version = InferVersion(source);
     var database = new TzdbDatabase(version);
     LoadZoneFiles(source, database);
     LoadLocationFiles(source, database);
     return database;
 }
Beispiel #8
0
        /// <summary>
        /// Parses the TZDB time zone info file from the given reader and merges its information
        /// with the given database. The reader is not closed or disposed.
        /// </summary>
        /// <param name="reader">The reader to read.</param>
        /// <param name="database">The database to fill.</param>
        internal void Parse(TextReader reader, TzdbDatabase database)
        {
            string currentZone = null;

            foreach (var line in reader.ReadLines())
            {
                currentZone = ParseLine(line, currentZone, database);
            }
        }
Beispiel #9
0
        /// <summary>
        /// Tries to compile the contents of a path to a TzdbDatabase. The path can be a directory
        /// name containing the TZDB files, or a local tar.gz file, or a remote tar.gz file.
        /// The version ID is taken from the Makefile, if it exists. Otherwise, an attempt is made to guess
        /// it based on the last element of the path, to match a regex of \d{2,4}[a-z] (anywhere within the element).
        /// </summary>
        public TzdbDatabase Compile(string path)
        {
            var source   = LoadSource(path);
            var version  = InferVersion(source);
            var database = new TzdbDatabase(version);

            LoadZoneFiles(source, database);
            LoadLocationFiles(source, database);
            return(database);
        }
Beispiel #10
0
        /// <summary>
        /// Tries to compile the contents of a path to a TzdbDatabase. The path can be a directory
        /// name containing the TZDB files, or a local tar.gz file, or a remote tar.gz file.
        /// The version ID is taken from the Makefile, if it exists. Otherwise, an attempt is made to guess
        /// it based on the last element of the path, to match a regex of \d{2,4}[a-z] (anywhere within the element).
        /// </summary>
        public async Task <TzdbDatabase> CompileAsync(string path)
        {
            var source = await LoadSourceAsync(path);

            var version  = InferVersion(source);
            var database = new TzdbDatabase(version);

            LoadZoneFiles(source, database);
            LoadLocationFiles(source, database);
            return(database);
        }
        internal TzdbDatabase Compile(string sourceDirectoryName)
        {
            Console.WriteLine("Starting compilation of directory {0}", sourceDirectoryName);
            var    sourceDirectory = new DirectoryInfo(sourceDirectoryName);
            var    fileList        = sourceDirectory.GetFiles().Where(file => !ExcludedFiles.Contains(file.Name));
            string version         = sourceDirectory.Name;
            var    database        = new TzdbDatabase(version);

            ParseAllFiles(fileList, database);
            database.ZoneLocations = TzdbZoneLocationParser.ParseFiles(sourceDirectory);
            return(database);
        }
 internal TzdbDatabase Compile(string sourceDirectoryName)
 {
     Console.WriteLine("Starting compilation of directory {0}", sourceDirectoryName);
     var sourceDirectory = new DirectoryInfo(sourceDirectoryName);
     var fileList = sourceDirectory.GetFiles().Where(file => !ExcludedFiles.Contains(file.Name));
     string version = sourceDirectory.Name;
     var database = new TzdbDatabase(version);
     ParseAllFiles(fileList, database);
     database.ZoneLocations = TzdbZoneLocationParser.ParseZoneTab(sourceDirectory);
     database.Zone1970Locations = TzdbZoneLocationParser.ParseZone1970Tab(sourceDirectory);
     return database;
 }
Beispiel #13
0
        /// <summary>
        /// Parses a single line of an TZDB zone info file.
        /// </summary>
        /// <remarks>
        /// <para>
        /// TZDB files have a simple line based structure. Each line defines one item. Comments
        /// start with a hash or pound sign (#) and continue to the end of the line. Blank lines are
        /// ignored. Of the remaining there are four line types which are determined by the first
        /// keyword on the line.
        /// </para>
        /// <para>
        /// A line beginning with the keyword <c>Link</c> defines an alias between one time zone and
        /// another. Both time zones use the same definition but have different names.
        /// </para>
        /// <para>
        /// A line beginning with the keyword <c>Rule</c> defines a daylight savings time
        /// calculation rule.
        /// </para>
        /// <para>
        /// A line beginning with the keyword <c>Zone</c> defines a time zone.
        /// </para>
        /// <para>
        /// A line beginning with leading whitespace (an empty keyword) defines another part of the
        /// preceeding time zone. As many lines as necessary to define the time zone can be listed,
        /// but they must all be together and only the first line can have a name.
        /// </para>
        /// </remarks>
        /// <param name="line">The line to parse.</param>
        /// <param name="database">The database to fill.</param>
        /// <return>The zone name just parsed, if any - so that it can be passed into the next call.</return>
        private string ParseLine(string line, string previousZone, TzdbDatabase database)
        {
            // Trim end-of-line comments
            int index = line.IndexOf("#", StringComparison.Ordinal);

            if (index >= 0)
            {
                line = line.Substring(0, index);
            }
            line = line.TrimEnd();
            if (line.Length == 0)
            {
                // We can still continue with the previous zone
                return(previousZone);
            }

            // Okay, everything left in the line should be "real" now.
            var tokens  = Tokens.Tokenize(line);
            var keyword = NextString(tokens, "Keyword");

            switch (keyword)
            {
            case KeywordRule:
                database.AddRule(ParseRule(tokens));
                return(null);

            case KeywordLink:
                var alias = ParseLink(tokens);
                database.AddAlias(alias.Item1, alias.Item2);
                return(null);

            case KeywordZone:
                var name = NextString(tokens, "GetName");
                database.AddZone(ParseZone(name, tokens));
                return(name);

            default:
                if (string.IsNullOrEmpty(keyword))
                {
                    if (previousZone == null)
                    {
                        throw new InvalidDataException("Zone continuation provided with no previous zone line");
                    }
                    database.AddZone(ParseZone(previousZone, tokens));
                    return(previousZone);
                }
                else
                {
                    throw new InvalidDataException($"Unexpected zone database keyword: {keyword}");
                }
            }
        }
Beispiel #14
0
        /// <summary>
        ///   Parses a single line of an TZDB zone info file.
        /// </summary>
        /// <remarks>
        ///   <para>
        ///     TZDB files have a simple line based structure. Each line defines one item. Comments
        ///     start with a hash or pound sign (#) and continue to the end of the line. Blank lines are
        ///     ignored. Of the remaining there are four line types which are determined by the first
        ///     keyword on the line.
        ///   </para>
        ///   <para>
        ///     A line beginning with the keyword <c>Link</c> defines an alias between one time zone and
        ///     another. Both time zones use the same definition but have different names.
        ///   </para>
        ///   <para>
        ///     A line beginning with the keyword <c>Rule</c> defines a daylight savings time
        ///     calculation rule.
        ///   </para>
        ///   <para>
        ///     A line beginning with the keyword <c>Zone</c> defines a time zone.
        ///   </para>
        ///   <para>
        ///     A line beginning with leading whitespace (an empty keyword) defines another part of the
        ///     preceeding time zone. As many lines as necessary to define the time zone can be listed,
        ///     but they must all be together and only the first line can have a name.
        ///   </para>
        /// </remarks>
        /// <param name="line">The line to parse.</param>
        /// <param name="database">The database to fill.</param>
        internal void ParseLine(string line, TzdbDatabase database)
        {
            int index = line.IndexOf("#", StringComparison.Ordinal);

            if (index == 0)
            {
                return;
            }
            if (index > 0)
            {
                line = line.Substring(0, index - 1);
            }
            line = line.TrimEnd();
            if (line.Length == 0)
            {
                return;
            }
            var tokens  = Tokens.Tokenize(line);
            var keyword = NextString(tokens, "Keyword");

            switch (keyword)
            {
            case KeywordRule:
                database.AddRule(ParseRule(tokens));
                break;

            case KeywordLink:
                database.AddAlias(ParseLink(tokens));
                break;

            case KeywordZone:
                var name      = NextString(tokens, "GetName");
                var namedZone = ParseZone(name, tokens);
                database.AddZone(namedZone);
                break;

            default:
                if (string.IsNullOrEmpty(keyword))
                {
                    var zone = ParseZone(string.Empty, tokens);
                    database.AddZone(zone);
                }
                else
                {
                    throw new InvalidDataException("Unexpected zone database keyword: " + keyword);
                }
                break;
            }
        }
Beispiel #15
0
        /// <summary>
        ///   Parses the TZDB time zone info file from the given reader and merges its information
        ///   with the given database. The reader is not closed or disposed.
        /// </summary>
        /// <param name="reader">The reader to read.</param>
        /// <param name="database">The database to fill.</param>
        public void Parse(TextReader reader, TzdbDatabase database)
        {
            bool firstLine = true;

            for (var line = reader.ReadLine(); line != null; line = reader.ReadLine())
            {
                // Only bother with files which start with comments.
                if (firstLine && !line.StartsWith("# ", StringComparison.Ordinal))
                {
                    return;
                }
                firstLine = false;
                ParseLine(line, database);
            }
        }
 private void LoadZoneFiles(FileSource source, TzdbDatabase database)
 {
     var tzdbParser = new TzdbZoneInfoParser();
     foreach (var file in ZoneFiles)
     {
         if (source.Contains(file))
         {
             log?.WriteLine("Parsing file {0} . . .", file);
             using (var stream = source.Open(file))
             {
                 tzdbParser.Parse(stream, database);
             }
         }
     }
 }
Beispiel #17
0
        private void LoadZoneFiles(FileSource source, TzdbDatabase database)
        {
            var tzdbParser = new TzdbZoneInfoParser();

            foreach (var file in ZoneFiles)
            {
                if (source.Contains(file))
                {
                    log?.WriteLine("Parsing file {0} . . .", file);
                    using (var stream = source.Open(file))
                    {
                        tzdbParser.Parse(stream, database);
                    }
                }
            }
        }
        public void Write(TzdbDatabase database, WindowsZones cldrWindowsZones)
        {
            FieldCollection fields = new FieldCollection();

            var zones      = database.GenerateDateTimeZones().ToList();
            var stringPool = CreateOptimizedStringPool(zones, database.ZoneLocations, cldrWindowsZones);

            // First assemble the fields (writing to the string pool as we go)
            foreach (var zone in zones)
            {
                var zoneField = fields.AddField(TzdbStreamFieldId.TimeZone, stringPool);
                WriteZone(zone, zoneField.Writer);
            }

            fields.AddField(TzdbStreamFieldId.TzdbVersion, null).Writer.WriteString(database.Version);

            // Normalize the aliases
            var timeZoneMap = new Dictionary <string, string>();

            foreach (var key in database.Aliases.Keys)
            {
                var value = database.Aliases[key];
                while (database.Aliases.ContainsKey(value))
                {
                    value = database.Aliases[value];
                }
                timeZoneMap.Add(key, value);
            }

            fields.AddField(TzdbStreamFieldId.TzdbIdMap, stringPool).Writer.WriteDictionary(timeZoneMap);

            // Windows mappings
            cldrWindowsZones.Write(fields.AddField(TzdbStreamFieldId.CldrSupplementalWindowsZones, stringPool).Writer);
            fields.AddField(TzdbStreamFieldId.WindowsAdditionalStandardNameToIdMapping, stringPool).Writer.WriteDictionary
                (PclSupport.StandardNameToIdMap.ToDictionary(pair => pair.Key, pair => cldrWindowsZones.PrimaryMapping[pair.Value]));

            // Zone locations, if any.
            var zoneLocations = database.ZoneLocations;

            if (zoneLocations != null)
            {
                var field = fields.AddField(TzdbStreamFieldId.ZoneLocations, stringPool);
                field.Writer.WriteCount(zoneLocations.Count);
                foreach (var zoneLocation in zoneLocations)
                {
                    zoneLocation.Write(field.Writer);
                }
            }

            var stringPoolField = fields.AddField(TzdbStreamFieldId.StringPool, null);

            stringPoolField.Writer.WriteCount(stringPool.Count);
            foreach (string value in stringPool)
            {
                stringPoolField.Writer.WriteString(value);
            }

            // Now write all the fields out, in the right order.
            new BinaryWriter(stream).Write(Version);
            fields.WriteTo(stream);

            stream.Close();
        }
 /// <summary>
 /// Parses a single line of an TZDB zone info file.
 /// </summary>
 /// <remarks>
 /// <para>
 /// TZDB files have a simple line based structure. Each line defines one item. Comments
 /// start with a hash or pound sign (#) and continue to the end of the line. Blank lines are
 /// ignored. Of the remaining there are four line types which are determined by the first
 /// keyword on the line.
 /// </para>
 /// <para>
 /// A line beginning with the keyword <c>Link</c> defines an alias between one time zone and
 /// another. Both time zones use the same definition but have different names.
 /// </para>
 /// <para>
 /// A line beginning with the keyword <c>Rule</c> defines a daylight savings time
 /// calculation rule.
 /// </para>
 /// <para>
 /// A line beginning with the keyword <c>Zone</c> defines a time zone.
 /// </para>
 /// <para>
 /// A line beginning with leading whitespace (an empty keyword) defines another part of the
 /// preceeding time zone. As many lines as necessary to define the time zone can be listed,
 /// but they must all be together and only the first line can have a name.
 /// </para>
 /// </remarks>
 /// <param name="line">The line to parse.</param>
 /// <param name="database">The database to fill.</param>
 internal void ParseLine(string line, TzdbDatabase database)
 {
     int index = line.IndexOf("#", StringComparison.Ordinal);
     if (index == 0)
     {
         return;
     }
     if (index > 0)
     {
         line = line.Substring(0, index - 1);
     }
     line = line.TrimEnd();
     if (line.Length == 0)
     {
         return;
     }
     var tokens = Tokens.Tokenize(line);
     var keyword = NextString(tokens, "Keyword");
     switch (keyword)
     {
         case KeywordRule:
             database.AddRule(ParseRule(tokens));
             break;
         case KeywordLink:
             database.AddAlias(ParseLink(tokens));
             break;
         case KeywordZone:
             var name = NextString(tokens, "GetName");
             var namedZone = ParseZone(name, tokens);
             database.AddZone(namedZone);
             break;
         default:
             if (string.IsNullOrEmpty(keyword))
             {
                 var zone = ParseZone(string.Empty, tokens);
                 database.AddZone(zone);
             }
             else
             {
                 throw new InvalidDataException($"Unexpected zone database keyword: {keyword}");
             }
             break;
     }
 }
 private static void ValidateCounts(TzdbDatabase database, int ruleSets, int zoneLists, int links)
 {
     Assert.AreEqual(ruleSets, database.Rules.Count, "Rules");
     Assert.AreEqual(zoneLists, database.ZoneLists.Count, "Zones");
     Assert.AreEqual(links, database.Aliases.Count, "Links");
 }
        /// <summary>
        /// Parses a single line of an TZDB zone info file.
        /// </summary>
        /// <remarks>
        /// <para>
        /// TZDB files have a simple line based structure. Each line defines one item. Comments
        /// start with a hash or pound sign (#) and continue to the end of the line. Blank lines are
        /// ignored. Of the remaining there are four line types which are determined by the first
        /// keyword on the line.
        /// </para>
        /// <para>
        /// A line beginning with the keyword <c>Link</c> defines an alias between one time zone and
        /// another. Both time zones use the same definition but have different names.
        /// </para>
        /// <para>
        /// A line beginning with the keyword <c>Rule</c> defines a daylight savings time
        /// calculation rule.
        /// </para>
        /// <para>
        /// A line beginning with the keyword <c>Zone</c> defines a time zone.
        /// </para>
        /// <para>
        /// A line beginning with leading whitespace (an empty keyword) defines another part of the
        /// preceeding time zone. As many lines as necessary to define the time zone can be listed,
        /// but they must all be together and only the first line can have a name.
        /// </para>
        /// </remarks>
        /// <param name="line">The line to parse.</param>
        /// <param name="database">The database to fill.</param>
        /// <return>The zone name just parsed, if any - so that it can be passed into the next call.</return>
        private string ParseLine(string line, string previousZone, TzdbDatabase database)
        {
            // Trim end-of-line comments
            int index = line.IndexOf("#", StringComparison.Ordinal);
            if (index >= 0)
            {
                line = line.Substring(0, index);
            }
            line = line.TrimEnd();
            if (line.Length == 0)
            {
                // We can still continue with the previous zone
                return previousZone;
            }

            // Okay, everything left in the line should be "real" now.
            var tokens = Tokens.Tokenize(line);
            var keyword = NextString(tokens, "Keyword");
            switch (keyword)
            {
                case KeywordRule:
                    database.AddRule(ParseRule(tokens));
                    return null;
                case KeywordLink:
                    var alias = ParseLink(tokens);
                    database.AddAlias(alias.Item1, alias.Item2);
                    return null;
                case KeywordZone:
                    var name = NextString(tokens, "GetName");
                    database.AddZone(ParseZone(name, tokens));
                    return name;
                default:
                    if (string.IsNullOrEmpty(keyword))
                    {
                        if (previousZone == null)
                        {
                            throw new InvalidDataException("Zone continuation provided with no previous zone line");
                        }
                        database.AddZone(ParseZone(previousZone, tokens));
                        return previousZone;
                    }
                    else
                    {
                        throw new InvalidDataException($"Unexpected zone database keyword: {keyword}");
                    }                    
            }
        }
 /// <summary>
 /// Parses the TZDB time zone info file from the given stream and merges its information
 /// with the given database. The stream is not closed or disposed.
 /// </summary>
 /// <param name="input">The stream input to parse.</param>
 /// <param name="database">The database to fill.</param>
 internal void Parse(Stream input, TzdbDatabase database)
 {
     Parse(new StreamReader(input, true), database);
 }
 /// <summary>
 /// Parses the TZDB time zone info file from the given reader and merges its information
 /// with the given database. The reader is not closed or disposed.
 /// </summary>
 /// <param name="reader">The reader to read.</param>
 /// <param name="database">The database to fill.</param>
 public void Parse(TextReader reader, TzdbDatabase database)
 {
     bool firstLine = true;
     for (var line = reader.ReadLine(); line != null; line = reader.ReadLine())
     {
         // Only bother with files which start with comments.
         if (firstLine && !line.StartsWith("# ", StringComparison.Ordinal))
         {
             return;
         }
         firstLine = false;
         ParseLine(line, database);
     }
 }
Beispiel #24
0
 private static List<DateTimeZone> LoadTzSources(IEnumerable<byte[]> sources)
 {
     var parser = new TzdbZoneInfoParser();
     var database = new TzdbDatabase(version: "ignored");
     foreach (var source in sources)
     {
         parser.Parse(new MemoryStream(source), database);
     }
     return database.GenerateDateTimeZones()
         .Concat(database.Aliases.Keys.Select(database.GenerateDateTimeZone))
         .ToList();            
 }
        public void Parse_Fixed_Western()
        {
            const string text = "# A comment\n" + "Zone\tEtc/GMT+9\t-9\t-\tGMT+9\n";
            var reader = new StringReader(text);
            var database = new TzdbDatabase("version");
            Parser.Parse(reader, database);

            ValidateCounts(database, 0, 1, 0);
            Assert.AreEqual(1, database.ZoneLists[0].Count, "Zones in set");
            var zone = database.ZoneLists[0][0];
            Assert.AreEqual(Offset.FromHours(-9), zone.Offset);
            Assert.IsNull(zone.Rules);
            Assert.AreEqual(int.MaxValue, zone.UntilYear);
        }
 public void Parse_twoZonesTwoRule()
 {
     const string text =
         "# A comment\n" + "Rule US 1987 2006 - Apr Sun>=1 2:00 1:00 D\n" + "Rule US 2007 max  - Mar Sun>=8 2:00 1:00 D\n" +
         "Zone PST 2:00 US P%sT # An end of line comment\n" + "         3:00 -  P%sT\n" + "         4:00 -  P%sT\n" +
         "Zone EST 2:00 US E%sT # An end of line comment\n" + "         3:00 -  E%sT\n";
     var reader = new StringReader(text);
     var database = new TzdbDatabase("version");
     Parser.Parse(reader, database);
     ValidateCounts(database, 1, 2, 0);
     Assert.AreEqual(2, database.ZoneLists[0].Count, "Zones in set " + database.ZoneLists[0].Name);
     Assert.AreEqual(3, database.ZoneLists[1].Count, "Zones in set " + database.ZoneLists[1].Name);
 }
 public void Parse_twoLinks()
 {
     const string text = "# First line must be a comment\n" + "Link from to\n" + "Link target source\n";
     var reader = new StringReader(text);
     var database = new TzdbDatabase("version");
     Parser.Parse(reader, database);
     ValidateCounts(database, 0, 0, 2);
 }
 public void Parse_twoLines()
 {
     const string text = "# A comment\n" + "Zone PST 2:00 US P%sT\n";
     var reader = new StringReader(text);
     var database = new TzdbDatabase("version");
     Parser.Parse(reader, database);
     ValidateCounts(database, 0, 1, 0);
     Assert.AreEqual(1, database.ZoneLists[0].Count, "Zones in set");
 }
Beispiel #29
0
        public void Write(
            TzdbDatabase database,
            WindowsZones cldrWindowsZones,
            IDictionary<string, string> additionalWindowsNameToIdMappings,
            Stream stream)
        {
            FieldCollection fields = new FieldCollection();

            var zones = database.GenerateDateTimeZones().ToList();
            var stringPool = CreateOptimizedStringPool(zones, database.ZoneLocations, database.Zone1970Locations, cldrWindowsZones);
            
            // First assemble the fields (writing to the string pool as we go)
            foreach (var zone in zones)
            {
                var zoneField = fields.AddField(TzdbStreamFieldId.TimeZone, stringPool);
                WriteZone(zone, zoneField.Writer);
            }

            fields.AddField(TzdbStreamFieldId.TzdbVersion, null).Writer.WriteString(database.Version);

            // Normalize the aliases
            var timeZoneMap = new Dictionary<string, string>();
            foreach (var key in database.Aliases.Keys)
            {
                var value = database.Aliases[key];
                while (database.Aliases.ContainsKey(value))
                {
                    value = database.Aliases[value];
                }
                timeZoneMap.Add(key, value);
            }

            fields.AddField(TzdbStreamFieldId.TzdbIdMap, stringPool).Writer.WriteDictionary(timeZoneMap);

            // Windows mappings
            cldrWindowsZones.Write(fields.AddField(TzdbStreamFieldId.CldrSupplementalWindowsZones, stringPool).Writer);
            fields.AddField(TzdbStreamFieldId.WindowsAdditionalStandardNameToIdMapping, stringPool).Writer.WriteDictionary
                (additionalWindowsNameToIdMappings.ToDictionary(pair => pair.Key, pair => cldrWindowsZones.PrimaryMapping[pair.Value]));

            // Zone locations, if any.
            var zoneLocations = database.ZoneLocations;
            if (zoneLocations != null)
            {
                var field = fields.AddField(TzdbStreamFieldId.ZoneLocations, stringPool);
                field.Writer.WriteCount(zoneLocations.Count);
                foreach (var zoneLocation in zoneLocations)
                {
                    zoneLocation.Write(field.Writer);
                }
            }

            // Zone 1970 locations, if any.
            var zone1970Locations = database.Zone1970Locations;
            if (zone1970Locations != null)
            {
                var field = fields.AddField(TzdbStreamFieldId.Zone1970Locations, stringPool);
                field.Writer.WriteCount(zone1970Locations.Count);
                foreach (var zoneLocation in zone1970Locations)
                {
                    zoneLocation.Write(field.Writer);
                }
            }

            var stringPoolField = fields.AddField(TzdbStreamFieldId.StringPool, null);
            stringPoolField.Writer.WriteCount(stringPool.Count);
            foreach (string value in stringPool)
            {
                stringPoolField.Writer.WriteString(value);
            }

            // Now write all the fields out, in the right order.
            new BinaryWriter(stream).Write(Version);
            fields.WriteTo(stream);
        }
        public void ParseLine_zonePlus()
        {
            const string line = "Zone PST 2:00 US P%sT";
            var database = new TzdbDatabase("version");
            Parser.ParseLine(line, database);

            const string line2 = "  3:00 US P%sT";
            Parser.ParseLine(line2, database);
            ValidateCounts(database, 0, 1, 0);
            Assert.AreEqual(2, database.ZoneLists[0].Count, "Zones in set");
        }
Beispiel #31
0
 /// <summary>
 /// Parses the TZDB time zone info file from the given stream and merges its information
 /// with the given database. The stream is not closed or disposed.
 /// </summary>
 /// <param name="input">The stream input to parse.</param>
 /// <param name="database">The database to fill.</param>
 internal void Parse(Stream input, TzdbDatabase database)
 {
     Parse(new StreamReader(input, true), database);
 }
 /// <summary>
 /// Helper method to create a database and call Parse with the given text.
 /// </summary>
 private TzdbDatabase ParseText(string line)
 {
     var parser = new TzdbZoneInfoParser();
     var database = new TzdbDatabase("version");
     parser.Parse(new StringReader(line), database);
     return database;
 }
 public void ParseLine_whiteSpace()
 {
     const string line = "    \t\t\n";
     var database = new TzdbDatabase("version");
     Parser.ParseLine(line, database);
     ValidateCounts(database, 0, 0, 0);
 }
 /// <summary>
 /// Parses the TZDB time zone info file from the given reader and merges its information
 /// with the given database. The reader is not closed or disposed.
 /// </summary>
 /// <param name="reader">The reader to read.</param>
 /// <param name="database">The database to fill.</param>
 internal void Parse(TextReader reader, TzdbDatabase database)
 {
     string currentZone = null;
     foreach (var line in reader.ReadLines())
     {
         currentZone = ParseLine(line, currentZone, database);
     }
 }
 public void ParseLine_commentWithLeadingWhitespace()
 {
     const string line = "   # Comment";
     var database = new TzdbDatabase("version");
     Parser.ParseLine(line, database);
     ValidateCounts(database, 0, 0, 0);
 }
 public void ParseLine_emptyString()
 {
     var database = new TzdbDatabase("version");
     Parser.ParseLine(string.Empty, database);
     ValidateCounts(database, 0, 0, 0);
 }
 public void Parse_emptyStream()
 {
     var reader = new StringReader(string.Empty);
     var database = new TzdbDatabase("version");
     Parser.Parse(reader, database);
     ValidateCounts(database, 0, 0, 0);
 }
 /// <summary>
 ///   Parses the file defined by the given <see cref="FileInfo" />.
 /// </summary>
 /// <remarks>
 ///   Currently this compiler only handles files in the Olson (TZDB) zone info format.
 /// </remarks>
 /// <param name="file">The file to parse.</param>
 /// <param name="database">The <see cref="TzdbDatabase" /> where the parsed data is placed.</param>
 internal void ParseFile(FileInfo file, TzdbDatabase database)
 {
     using (FileStream stream = file.OpenRead())
     {
         tzdbParser.Parse(stream, database);
     }
 }
 public void ParseLine_link()
 {
     const string line = "Link from to";
     var database = new TzdbDatabase("version");
     Parser.ParseLine(line, database);
     ValidateCounts(database, 0, 0, 1);
 }