[System.Core/Android] Update TimeZone database self test.
authorJonathan Pryor <jonpryor@vt.edu>
Thu, 30 Oct 2014 16:33:33 +0000 (12:33 -0400)
committerJonathan Pryor <jonpryor@vt.edu>
Thu, 30 Oct 2014 16:42:37 +0000 (12:42 -0400)
Add Makefile rules to automagically download the TimeZone database
from the Android target $(ADB_TARGET), and build the tzi.exe app.

$ make android-dump-tzdata ADB_TARGET=-d
# downloads timezone data into ./android/tzdb.
# dumps timezone data into ./android/tzdata
# builds ./tzi.exe

# Show adjustment rules for a given timezone dump
$ mono tzi.exe -i=tzdata/Asia/Amman

Add `tzi.exe -R` option to show the TimeZoneInfo.GetAdjustmentRules()
output for all encountered timezones.

Add `tzi.exe -o=PATH` option to dump the TimeZone data to disk for
interrogation.

Add `tzi.exe -i=PATH` option to read in the specified TimeZone data
file and dump the rules contained therein.

Update usage comments.

mcs/class/System.Core/Makefile
mcs/class/System.Core/System/TimeZoneInfo.Android.cs

index f8cc33c7e8b94afff4a3eb58bfa11aa6c8cc1c0d..eeca6391a148100f8f228a3eaf03059b546f4320 100644 (file)
@@ -72,3 +72,22 @@ csproj-local:
        $(MAKE) csproj-local intermediate=plaincore/
 endif
 endif
+
+#
+# Android TimeZoneInfo testing....
+#
+
+tzi.exe: ../corlib/System/AndroidPlatform.cs $(wildcard System/TimeZone*.cs) ../../build/common/Consts.cs ../Mono.Options/Mono.Options/Options.cs
+       mcs /debug+ /out:$@ /unsafe "/d:INSIDE_CORLIB;MONODROID;NET_4_0;LIBC;SELF_TEST" $^
+
+android-pull-tzdb:
+       mkdir -p android/tzdb/usr/share/zoneinfo
+       mkdir -p android/tzdb/misc/zoneinfo/zoneinfo
+       android_root=`adb shell echo '$$ANDROID_ROOT' | tr -d "\r"` ; \
+       android_data=`adb shell echo '$$ANDROID_DATA' | tr -d "\r"` ; \
+       adb $(ADB_TARGET) pull $$android_root/usr/share/zoneinfo    android/tzdb/usr/share/zoneinfo ; \
+       adb $(ADB_TARGET) pull $$android_data/misc/zoneinfo/tzdata  android/tzdb/misc/zoneinfo
+       mkdir -p android/tzdb/
+
+android-dump-tzdata: tzi.exe android-pull-tzdb
+       __XA_OVERRIDE_TIMEZONE_ID__=America/New_York ANDROID_ROOT=`pwd` ANDROID_DATA=`pwd` mono --debug tzi.exe -o android/tzdata
index 079af3722d6cc9b4882304c15ee1a750aad7bc31..72285cc0dabadf6032c97d63bafac2674df74c65 100644 (file)
@@ -246,6 +246,7 @@ namespace System {
                                                                tzdataPath, offset, length, r, buffer.Length));
                        }
 
+                       TimeZoneInfo.DumpTimeZoneDataToFile (id, buffer);
                        return buffer;
                }
        }
@@ -581,21 +582,37 @@ namespace System {
                         * Compile:
                         *    mcs /debug+ /out:tzi.exe /unsafe "/d:INSIDE_CORLIB;MONODROID;NET_4_0;LIBC;SELF_TEST" ../corlib/System/AndroidPlatform.cs System/TimeZone*.cs ../../build/common/Consts.cs ../Mono.Options/Mono.Options/Options.cs
                         * Prep:
-                        *    mkdir -p usr/share/zoneinfo
-                        *    mkdir -p misc/zoneinfo/zoneinfo
+                        *    mkdir -p android/tzdb/usr/share/zoneinfo
+                        *    mkdir -p android/tzdb/misc/zoneinfo/zoneinfo
                         *    android_root=`adb shell echo '$ANDROID_ROOT' | tr -d "\r"`
                         *    android_data=`adb shell echo '$ANDROID_DATA' | tr -d "\r"`
-                        *    adb pull $android_root/usr/share/zoneinfo usr/share/zoneinfo
-                        *    adb pull $android_data/misc/zoneinfo/tzdata misc/zoneinfo
+                        *    adb pull $android_root/usr/share/zoneinfo   android/tzdb/usr/share/zoneinfo
+                        *    adb pull $android_data/misc/zoneinfo/tzdata android/tzdb/misc/zoneinfo
                         * Run:
+                        *    # Dump all timezone names
                         *    __XA_OVERRIDE_TIMEZONE_ID__=America/New_York ANDROID_ROOT=`pwd` ANDROID_DATA=`pwd` mono --debug tzi.exe --offset=1969-01-01
+                        *
+                        *    # Dump TimeZone data to files under path `tzdata`
+                        *    __XA_OVERRIDE_TIMEZONE_ID__=America/New_York ANDROID_ROOT=`pwd` ANDROID_DATA=`pwd` mono --debug tzi.exe -o android/tzdata
+                        *
+                        *    # Dump TimeZone rules for specific timezone data (as dumped above)
+                        *    mono tzi.exe --offset=2012-10-24 -i=tzdata/Asia/Amman
                         */
                        static void Main (string[] args)
                        {
                                DateTime? offset           = null;
                                Func<IAndroidTimeZoneDB> c = () => GetDefaultTimeZoneDB ();
+                               bool dump_rules            = false;
                                Mono.Options.OptionSet p = null;
                                p = new Mono.Options.OptionSet () {
+                                       { "i=",
+                                         "TimeZone data {FILE} to parse and dump",
+                                         v => DumpTimeZoneFile (v, offset)
+                                       },
+                                       { "o=",
+                                         "Write TimeZone data files to {PATH}",
+                                         v => TimeZoneInfo.TimeZoneDataExportPath = v
+                                       },
                                        { "T=", "Create AndroidTzData from {PATH}.", v => {
                                                        c = () => new AndroidTzData (v);
                                        } },
@@ -606,6 +623,9 @@ namespace System {
                                                offset = DateTime.Parse (v);
                                                Console.WriteLine ("Using DateTime Offset: {0}", offset);
                                        } },
+                                       { "R|dump-rules",
+                                         "Show timezone info offset for DateTime {OFFSET}.",
+                                         v => dump_rules = v != null },
                                        { "help", "Show this message and exit", v => {
                                                        p.WriteOptionDescriptions (Console.Out);
                                                        Environment.Exit (0);
@@ -623,6 +643,9 @@ namespace System {
                                                        if (offset.HasValue) {
                                                                Console.Write ("From Offset: {0}", zone.GetUtcOffset (offset.Value));
                                                        }
+                                                       if (dump_rules) {
+                                                               WriteZoneRules (zone);
+                                                       }
                                                }
                                                else {
                                                        Console.Write (" ERROR:null");
@@ -634,6 +657,53 @@ namespace System {
                                        Console.WriteLine ();
                                }
                        }
+
+                       static void WriteZoneRules (TimeZoneInfo zone)
+                       {
+                               var rules = zone.GetAdjustmentRules ();
+                               for (int i = 0; i < rules.Length; ++i) {
+                                       var rule = rules [i];
+                                       Console.WriteLine ();
+                                       Console.Write ("\tAdjustmentRules[{0,3}]: DaylightDelta={1}; DateStart={2:yyyy-MM}; DateEnd={3:yyyy-MM}; DaylightTransitionStart={4:D2}-{5:D2}T{6}; DaylightTransitionEnd={7:D2}-{8:D2}T{9}",
+                                               i,
+                                               rule.DaylightDelta,
+                                               rule.DateStart, rule.DateEnd,
+                                               rule.DaylightTransitionStart.Month, rule.DaylightTransitionStart.Day, rule.DaylightTransitionStart.TimeOfDay.TimeOfDay,
+                                               rule.DaylightTransitionEnd.Month, rule.DaylightTransitionEnd.Day, rule.DaylightTransitionEnd.TimeOfDay.TimeOfDay);
+                               }
+                       }
+
+                       static void DumpTimeZoneFile (string path, DateTime? time)
+                       {
+                               var buffer = File.ReadAllBytes (path);
+                               var zone = ParseTZBuffer (path, buffer, buffer.Length);
+                               Console.Write ("Rules for: {0}", path);
+                               WriteZoneRules (zone);
+                               Console.WriteLine ();
+                               if (time.HasValue) {
+                                       var offset = zone.GetUtcOffset (time.Value);
+                                       var isDst  = zone.IsDaylightSavingTime (time.Value);
+                                       Console.WriteLine ("\tDate({0}): Offset({1}) IsDST({2})", time.Value, offset, isDst);
+                               }
+                       }
+#endif
+               }
+
+#if SELF_TEST
+               static string TimeZoneDataExportPath;
+#endif
+
+               internal static void DumpTimeZoneDataToFile (string id, byte[] buffer)
+               {
+#if SELF_TEST
+                       int p = id.LastIndexOf ('/');
+                       var o = Path.Combine (TimeZoneDataExportPath,
+                                       p >= 0 ? id.Substring (0, p) : id);
+                       if (p >= 0)
+                               o = Path.Combine (o, id.Substring (p+1));
+                       Directory.CreateDirectory (Path.GetDirectoryName (o));
+                       using (var f = File.OpenWrite (o))
+                               f.Write (buffer, 0, buffer.Length);
 #endif
                }
        }