1/**
2 * FreeRDP: A Remote Desktop Protocol Implementation
3 * Time Zone Redirection Table Generator
4 *
5 * Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 *	 http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19/* Run with ' csi scripts/TimeZones.csx' from freerdp checkout root */
20
21using System;
22using System.IO;
23using System.Globalization;
24using System.Collections.ObjectModel;
25
26struct SYSTEM_TIME_ENTRY
27{
28    public UInt16 wYear;
29    public UInt16 wMonth;
30    public UInt16 wDayOfWeek;
31    public UInt16 wDay;
32    public UInt16 wHour;
33    public UInt16 wMinute;
34    public UInt16 wSecond;
35    public UInt16 wMilliseconds;
36};
37
38struct TIME_ZONE_RULE_ENTRY
39{
40    public long TicksStart;
41    public long TicksEnd;
42    public Int32 DaylightDelta;
43    public SYSTEM_TIME_ENTRY StandardDate;
44    public SYSTEM_TIME_ENTRY DaylightDate;
45};
46
47struct TIME_ZONE_ENTRY
48{
49    public string Id;
50    public Int32 Bias;
51    public bool SupportsDST;
52    public string DisplayName;
53    public string StandardName;
54    public string DaylightName;
55    public string RuleTable;
56    public UInt32 RuleTableCount;
57};
58
59int i;
60UInt32 index;
61const string file = @"winpr/libwinpr/timezone/TimeZones.c";
62TimeZoneInfo.AdjustmentRule[] rules;
63StreamWriter stream = new StreamWriter(file, false);
64ReadOnlyCollection<TimeZoneInfo> timeZones = TimeZoneInfo.GetSystemTimeZones();
65
66Console.WriteLine("Updating " + file);
67stream.WriteLine("/* ");
68stream.WriteLine(" * Automatically generated with scripts/TimeZones.csx");
69stream.WriteLine(" */ ");
70stream.WriteLine();
71
72stream.WriteLine("#include \"TimeZones.h\"");
73stream.WriteLine();
74
75index = 0;
76
77foreach (TimeZoneInfo timeZone in timeZones)
78{
79    rules = timeZone.GetAdjustmentRules();
80
81    if ((!timeZone.SupportsDaylightSavingTime) || (rules.Length < 1))
82    {
83        index++;
84        continue;
85    }
86
87    stream.WriteLine("static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_{0}[] =", index);
88    stream.WriteLine("{");
89
90    i = 0;
91    foreach (TimeZoneInfo.AdjustmentRule rule in rules)
92    {
93        DateTime time;
94        TIME_ZONE_RULE_ENTRY tzr;
95        TimeZoneInfo.TransitionTime transition;
96
97        tzr.TicksStart = rule.DateEnd.ToUniversalTime().Ticks;
98        tzr.TicksEnd = rule.DateStart.ToUniversalTime().Ticks;
99        tzr.DaylightDelta = (Int32)rule.DaylightDelta.TotalMinutes;
100
101        transition = rule.DaylightTransitionEnd;
102        time = transition.TimeOfDay;
103
104        tzr.StandardDate.wYear = (UInt16)0;
105        tzr.StandardDate.wMonth = (UInt16)transition.Month;
106        tzr.StandardDate.wDayOfWeek = (UInt16)transition.DayOfWeek;
107        tzr.StandardDate.wDay = (UInt16)transition.Week;
108        tzr.StandardDate.wHour = (UInt16)time.Hour;
109        tzr.StandardDate.wMinute = (UInt16)time.Minute;
110        tzr.StandardDate.wSecond = (UInt16)time.Second;
111        tzr.StandardDate.wMilliseconds = (UInt16)time.Millisecond;
112
113        transition = rule.DaylightTransitionStart;
114        time = transition.TimeOfDay;
115
116        tzr.DaylightDate.wYear = (UInt16)0;
117        tzr.DaylightDate.wMonth = (UInt16)transition.Month;
118        tzr.DaylightDate.wDayOfWeek = (UInt16)transition.DayOfWeek;
119        tzr.DaylightDate.wDay = (UInt16)transition.Week;
120        tzr.DaylightDate.wHour = (UInt16)time.Hour;
121        tzr.DaylightDate.wMinute = (UInt16)time.Minute;
122        tzr.DaylightDate.wSecond = (UInt16)time.Second;
123        tzr.DaylightDate.wMilliseconds = (UInt16)time.Millisecond;
124
125        stream.Write("\t{");
126        stream.Write(" {0}ULL, {1}ULL, {2},", tzr.TicksStart, tzr.TicksEnd, tzr.DaylightDelta);
127
128        stream.Write(" { ");
129        stream.Write("{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}",
130            tzr.StandardDate.wYear, tzr.StandardDate.wMonth, tzr.StandardDate.wDayOfWeek,
131            tzr.StandardDate.wDay, tzr.StandardDate.wHour, tzr.StandardDate.wMinute,
132            tzr.StandardDate.wSecond, tzr.StandardDate.wMilliseconds);
133        stream.Write(" }, ");
134
135        stream.Write("{ ");
136        stream.Write("{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}",
137            tzr.DaylightDate.wYear, tzr.DaylightDate.wMonth, tzr.DaylightDate.wDayOfWeek,
138            tzr.DaylightDate.wDay, tzr.DaylightDate.wHour, tzr.DaylightDate.wMinute,
139            tzr.DaylightDate.wSecond, tzr.DaylightDate.wMilliseconds);
140        stream.Write(" },");
141
142        if (++i < rules.Length)
143            stream.WriteLine(" },");
144        else
145            stream.WriteLine(" }");
146    }
147
148    stream.WriteLine("};");
149    stream.WriteLine();
150    index++;
151}
152
153index = 0;
154stream.WriteLine("const TIME_ZONE_ENTRY TimeZoneTable[] =");
155stream.WriteLine("{");
156
157foreach (TimeZoneInfo timeZone in timeZones)
158{
159    TIME_ZONE_ENTRY tz;
160    TimeSpan offset = timeZone.BaseUtcOffset;
161
162    rules = timeZone.GetAdjustmentRules();
163
164    tz.Id = timeZone.Id;
165    tz.Bias = -(Int32)offset.TotalMinutes;
166
167    tz.SupportsDST = timeZone.SupportsDaylightSavingTime;
168
169    tz.DisplayName = timeZone.DisplayName;
170    tz.StandardName = timeZone.StandardName;
171    tz.DaylightName = timeZone.DaylightName;
172
173    if ((!tz.SupportsDST) || (rules.Length < 1))
174    {
175        tz.RuleTableCount = 0;
176        tz.RuleTable = "NULL";
177    }
178    else
179    {
180        tz.RuleTableCount = (UInt32)rules.Length;
181        tz.RuleTable = "TimeZoneRuleTable_" + index;
182    }
183
184    stream.WriteLine("\t{");
185
186    stream.WriteLine("\t\t\"{0}\", {1}, {2}, \"{3}\",",
187        tz.Id, tz.Bias, tz.SupportsDST ? "TRUE" : "FALSE", tz.DisplayName);
188
189    stream.WriteLine("\t\t\"{0}\", \"{1}\",", tz.StandardName, tz.DaylightName);
190    stream.WriteLine("\t\t{0}, {1}", tz.RuleTable, tz.RuleTableCount);
191
192    index++;
193
194    if ((int)index < timeZones.Count)
195        stream.WriteLine("\t},");
196    else
197        stream.WriteLine("\t}");
198}
199stream.WriteLine("};");
200stream.WriteLine();
201stream.WriteLine("const size_t TimeZoneTableNrElements = ARRAYSIZE(TimeZoneTable);");
202stream.WriteLine();
203
204stream.Close();
205
206