/// <summary> /// Parses TimeZones and Rules from the files in the provided /// Olson/TZ Database directory. The directory provided must be a valid TZ Database. /// </summary> /// <param name="directory">The valid directory to parse Rules and TimeZones from.</param> public void ReadTZDirectory() { try { // Mapping from TZname to: id, Ccode, Cname. var tzNameToInfo = ReadTabFiles(); TimeZones.BeginLoadData(); Rules.BeginLoadData(); Leaps.BeginLoadData(); foreach (OlsonFileInfo file in _olsonFiles.GetConsumingEnumerable()) { if (!file.IsTabFile) { RaiseFileParsing(file); string[] lines = File.ReadAllLines(file.FullName); // Process items. for (int i = 0; i < lines.Length; i++) { string line = lines[i].TrimStart(); if (!isCommentNullOrWhiteSpace(line)) { string[] fields = ParseFields(line); switch (fields[0]) { case Rule.RULE_NAME: { short from = Rule.ParseStartYear(fields[Rule.FromIndex]); short to = Rule.ParseEndYear(fields[Rule.ToIndex], from); if (from > _curYear || to < _curYear) { continue; } // No parsing necessary. string name = fields[Rule.NameIndex]; var rule = Rules.NewRow(); rule[1] = name; rule[2] = Rule.ParseBias(fields[Rule.SaveIndex]); rule[3] = from; rule[4] = to; rule[5] = Rule.ParseMonth(fields[Rule.InIndex]); rule[6] = fields[Rule.OnIndex]; rule[7] = Rule.ParseTime(fields[Rule.AtIndex]); rule[8] = Rule.ParseTimeType(ref fields[Rule.AtIndex]); rule[9] = Rule.ParseAbrev(fields[Rule.LetterIndex]) ?? (object)System.DBNull.Value; _ruleRows.Add(rule); RaiseEntryParsed(null); break; } case TimeZone.ZONE_NAME: { // First TZ. int init = i; // Count to last do { i++; } while (i < lines.Length && TimeZone.IsContinuation(lines[i])); // If first was not the only... if (i - init != 1) { string[] continuation = ParseFields(lines[--i].Trim()); // Continuation has a non-tab delimited date... if (continuation.Length > 4 && int.Parse(continuation[3]) < _curYear) { continue; } System.Array.Copy(continuation, 0, fields, 2, continuation.Length); } else { if (fields.Length > 5 && int.Parse(fields[5]) < _curYear) { continue; } } string name = TimeZone.ParseName(fields[TimeZone.NameIndex]); string countryCode = null; string countryName = null; string coord = null; string comments = null; int id = 0; string[] tokens; if (tzNameToInfo.TryGetValue(name, out tokens)) { id = System.Convert.ToInt32(tokens[0]); countryCode = tokens[1]; countryName = tokens[2]; coord = tokens[3]; comments = tokens[4]; } else { App.ExceptionLogger.LogLow(new System.Exception("OlsonParser.cs Ln 390:" + "Error attempting to get a TimeZone's iso/tab info.")); continue; } short bias = TimeZone.ParseBias(fields[TimeZone.GMTOffsetIndex]); string ruleName = TimeZone.ParseRuleName(fields[TimeZone.RuleIndex]); string tzAbrev = TimeZone.ParseTzAbrev(fields[TimeZone.FormatIndex]); var timeZone = TimeZones.NewRow(); timeZone[0] = id; timeZone[1] = name; timeZone[2] = bias; timeZone[3] = ruleName; timeZone[4] = tzAbrev; timeZone[5] = countryCode; timeZone[6] = countryName; timeZone[7] = comments; timeZone[8] = coord; TimeZoneLookupTable[name] = timeZone; _timeZoneRows.Add(timeZone); RaiseEntryParsed(null); break; } case Link.LINK_NAME: { var link = new string[] { fields[Link.FromZoneNameIndex], fields[Link.ToZoneNameIndex] }; _links.Add(link); RaiseEntryParsed(null); break; } case Leap.LEAP_NAME: { var leap = Leaps.NewRow(); leap[1] = Leap.ParseYear(fields[Leap.YearIndex]); leap[2] = fields[Leap.MonthIndex]; leap[3] = Leap.ParseDay(fields[Leap.DayIndex]); leap[4] = Leap.ParseTime(fields[Leap.TimeIndex]); leap[5] = Leap.ParseCorrection(fields[Leap.CorrectionIndex]); leap[6] = Leap.ParseRs(fields[Leap.RsIndex]); _leapRows.Add(leap); RaiseEntryParsed(null); break; } } ParsedEntries++; } } RaiseFileParsed(file); } } // Adding all links to list of TimeZones. foreach (string[] link in _links) { System.Data.DataRow from; if (!TimeZoneLookupTable.TryGetValue(link[Link.FromZoneNameIndex], out from)) { App.ExceptionLogger.LogLow(new System.Exception("OlsonParser.cs Ln 364: Error attempting to find the \"From\" TimeZone for the link:" + link[0].ToString())); continue; } string toName = link[Link.ToZoneNameIndex]; System.Data.DataRow to = TimeZones.NewRow(); to[0] = ++_lastUID; to[1] = toName; to[2] = from[2]; to[3] = from[3]; to[4] = from[4]; to[5] = from[5]; to[6] = from[6]; to[7] = from[7]; to[8] = from[8]; if (!TimeZoneLookupTable.TryAdd(toName, to)) { App.ExceptionLogger.LogLow(new System.Exception("OlsonParser.cs Ln 373: Error attempting to add the TimeZone for the link:" + link.ToString())); continue; } try { _timeZoneRows.Add(to); RaiseEntryParsed(null); ParsedEntries++; } catch (System.Exception e) { App.ExceptionLogger.LogLow(e); continue; } } RaiseDirectoryParsed(Directory); } finally { TimeZones.EndLoadData(); Rules.EndLoadData(); Leaps.EndLoadData(); } }