////////////////////////////////////////////////////////////////////////// // Database ////////////////////////////////////////////////////////////////////////// // // TimeZone database format: // // ftz // { // u8 magic ("fantz 02") // utf summary // u1 numPrefixes // utf[] prefixes // u2 numIndexItems // indexItems[] // sorted by name // { // u1 prefix id // utf name // u4 fileOffset // } // timeZones[] // { // u2 numRules // rules[] // { // u2 startYear // i4 utcOffset (seconds) // utf stdAbbr // i4 dstOffset (seconds); if zero rest is skipped // [ // utf dstAbbr // dstTime dstStart // dstTime dstEnd // ] // } // } // // dstTime // { // u1 month // u1 onMode 'd', 'l', '>', '<' (date, last, >=, and <=) // u1 onWeekday (0-6) // u1 onDay // i4 atTime (seconds) // u1 atMode 'w' , 's', 'u' (wall, standad, universal) // } // // The timezone database is generated by the "/adm/buildtz.fan" // script. Refer to the "zic.8.txt" source file the code // distribution of the Olson database to further describe // model of the original data. // /// <summary> /// Load the name and file offset list from file into memory. /// </summary> static void loadIndex() { DataReader reader = new DataReader(new BufferedStream(dbFile.OpenRead())); try { // check magic "fantz 02" long magic = reader.ReadLong(); if (magic != 0x66616e747a203032L) throw new IOException("Invalid magic 0x" + magic.ToString("X").ToLower()); reader.ReadUTF(); // load prefixes int numPrefixes = reader.ReadByte(); prefixes = new string[numPrefixes]; for (int i=0; i<numPrefixes; ++i) prefixes[i] = reader.ReadUTF(); // load the zones and verify in sort order int num = reader.ReadUnsignedShort(); indexPrefixes = new byte[num]; indexNames = new string[num]; indexOffsets = new int[num]; for (int i=0; i<num; ++i) { indexPrefixes[i] = reader.ReadByte(); indexNames[i] = reader.ReadUTF(); indexOffsets[i] = reader.ReadInt(); if (i != 0 && String.Compare(indexNames[i-1], indexNames[i], StringComparison.Ordinal) >= 0) throw new IOException("Index not sorted"); } } finally { reader.Close(); } }
/* static void loadIndex() { DataReader reader = new DataReader(new BufferedStream(dbFile.OpenRead())); try { // check magic "fantz 01" long magic = reader.ReadLong(); if (magic != 0x66616e747a203031L) throw new IOException("Invalid magic 0x" + magic.ToString("X").ToLower()); reader.ReadUTF(); // load the name/offset pairs and verify in sort order int num = reader.ReadInt(); indexNames = new string[num]; indexTypes = new byte[num]; indexOffsets = new int[num]; for (int i=0; i<num; ++i) { indexNames[i] = reader.ReadUTF(); indexTypes[i] = (byte)reader.ReadByte(); indexOffsets[i] = reader.ReadInt(); if (i != 0 && String.Compare(indexNames[i-1], indexNames[i], StringComparison.Ordinal) >= 0) throw new IOException("Index not sorted"); } } finally { reader.Close(); } } static TimeZone loadTimeZone(string name) { // find index, which maps the file offset int ix = Array.BinarySearch(indexNames, name); if (ix < 0) return null; int seekOffset = indexOffsets[ix]; // create time zone instance TimeZone tz = new TimeZone(); tz.m_name = name; // read time zone definition from database file FileStream f = dbFile.OpenRead(); DataReader d = new DataReader(f); try { f.Seek(seekOffset, SeekOrigin.Begin); tz.m_name = d.ReadUTF(); tz.m_fullName = d.ReadUTF(); int numRules = d.ReadUnsignedShort(); tz.rules = new Rule[numRules]; for (int i=0; i<numRules; ++i) { Rule r = tz.rules[i] = new Rule(); r.startYear = d.ReadUnsignedShort(); r.offset = d.ReadInt(); r.stdAbbr = d.ReadUTF(); r.dstOffset = d.ReadInt(); if (r.dstOffset == 0) continue; r.dstAbbr = d.ReadUTF(); r.dstStart = loadDstTime(d); r.dstEnd = loadDstTime(d); if (i != 0 && tz.rules[i-1].startYear <= r.startYear) throw new IOException("TimeZone rules not sorted: " + name); } } finally { f.Close(); } return tz; } */ static DstTime loadDstTime(DataReader d) { DstTime t = new DstTime(); t.mon = d.ReadByte(); t.onMode = d.ReadByte(); t.onWeekday = d.ReadByte(); t.onDay = d.ReadByte(); t.atTime = d.ReadInt(); t.atMode = d.ReadByte(); return t; }