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); } }
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; }
/// <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); } }
/// <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); }
/// <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; }
/// <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 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; } }
/// <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); } } } }
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); }
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"); }
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"); }
/// <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); }
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); }
public void ParseLine_link() { const string line = "Link from to"; var database = new TzdbDatabase("version"); Parser.ParseLine(line, database); ValidateCounts(database, 0, 0, 1); }