/// <summary> /// Initializes a new instance of the <see cref="TimeZoneDefinition"/> class. /// </summary> /// <param name="timeZoneInfo">The time zone info used to initialize this definition.</param> internal TimeZoneDefinition(TimeZoneInfo timeZoneInfo) : this() { this.Id = timeZoneInfo.Id; this.Name = timeZoneInfo.DisplayName; // TimeZoneInfo only supports one standard period, which bias is the time zone's base // offset to UTC. TimeZonePeriod standardPeriod = new TimeZonePeriod(); standardPeriod.Id = TimeZonePeriod.StandardPeriodId; standardPeriod.Name = TimeZonePeriod.StandardPeriodName; standardPeriod.Bias = -timeZoneInfo.BaseUtcOffset; TimeZoneInfo.AdjustmentRule[] adjustmentRules = timeZoneInfo.GetAdjustmentRules(); TimeZoneTransition transitionToStandardPeriod = new TimeZoneTransition(this, standardPeriod); if (adjustmentRules.Length == 0) { this.periods.Add(standardPeriod.Id, standardPeriod); // If the time zone info doesn't support Daylight Saving Time, we just need to // create one transition to one group with one transition to the standard period. TimeZoneTransitionGroup transitionGroup = new TimeZoneTransitionGroup(this, "0"); transitionGroup.Transitions.Add(transitionToStandardPeriod); this.transitionGroups.Add(transitionGroup.Id, transitionGroup); TimeZoneTransition initialTransition = new TimeZoneTransition(this, transitionGroup); this.transitions.Add(initialTransition); } else { for (int i = 0; i < adjustmentRules.Length; i++) { TimeZoneTransitionGroup transitionGroup = new TimeZoneTransitionGroup(this, this.transitionGroups.Count.ToString()); transitionGroup.InitializeFromAdjustmentRule(adjustmentRules[i], standardPeriod); this.transitionGroups.Add(transitionGroup.Id, transitionGroup); TimeZoneTransition transition; if (i == 0) { // If the first adjustment rule's start date in not undefined (DateTime.MinValue) // we need to add a dummy group with a single, simple transition to the Standard // period and a group containing the transitions mapping to the adjustment rule. if (adjustmentRules[i].DateStart > DateTime.MinValue.Date) { TimeZoneTransition transitionToDummyGroup = new TimeZoneTransition( this, this.CreateTransitionGroupToPeriod(standardPeriod)); this.transitions.Add(transitionToDummyGroup); AbsoluteDateTransition absoluteDateTransition = new AbsoluteDateTransition(this, transitionGroup); absoluteDateTransition.DateTime = adjustmentRules[i].DateStart; transition = absoluteDateTransition; this.periods.Add(standardPeriod.Id, standardPeriod); } else { transition = new TimeZoneTransition(this, transitionGroup); } } else { AbsoluteDateTransition absoluteDateTransition = new AbsoluteDateTransition(this, transitionGroup); absoluteDateTransition.DateTime = adjustmentRules[i].DateStart; transition = absoluteDateTransition; } this.transitions.Add(transition); } } }
private static void DoRunWithLEProfile(string path, LEProfile profile) { try { if (profile.RunWithSuspend) { if (DialogResult.No == MessageBox.Show( "You are running a process with CREATE_SUSPEND flag.\r\nIs this really what you want?", "Locale Emulator Debug Mode Warning", MessageBoxButtons.YesNo)) return; } string applicationName = string.Empty; string commandLine = string.Empty; if (Path.GetExtension(path).ToLower() == ".exe") { applicationName = path; commandLine = path.StartsWith("\"") ? string.Format("{0} ", path) : String.Format("\"{0}\" ", path); commandLine += profile.Parameter; } else { string[] jb = AssociationReader.GetAssociatedProgram(Path.GetExtension(path)); if (jb == null) return; applicationName = jb[0]; commandLine = jb[0].StartsWith("\"") ? string.Format("{0} ", jb[0]) : String.Format("\"{0}\" ", jb[0]); commandLine += jb[1].Replace("%1", path).Replace("%*", profile.Parameter); } string currentDirectory = Path.GetDirectoryName(path); bool debugMode = profile.RunWithSuspend; var ansiCodePage = (uint)CultureInfo.GetCultureInfo(profile.Location).TextInfo.ANSICodePage; var oemCodePage = (uint)CultureInfo.GetCultureInfo(profile.Location).TextInfo.OEMCodePage; var localeID = (uint)CultureInfo.GetCultureInfo(profile.Location).TextInfo.LCID; var defaultCharset = (uint) GetCharsetFromANSICodepage( CultureInfo.GetCultureInfo(profile.Location).TextInfo.ANSICodePage); string defaultFaceName = profile.DefaultFont; TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById(profile.Timezone); var timezoneBias = (int)-tzi.BaseUtcOffset.TotalMinutes; TimeZoneInfo.AdjustmentRule[] adjustmentRules = tzi.GetAdjustmentRules(); TimeZoneInfo.AdjustmentRule adjustmentRule = null; if (adjustmentRules.Length > 0) { // Find the single record that encompasses today's date. If none exists, sets adjustmentRule to null. adjustmentRule = adjustmentRules.SingleOrDefault(ar => ar.DateStart <= DateTime.Now && DateTime.Now <= ar.DateEnd); } int timezoneDaylightBias = adjustmentRule == null ? 0 : (int)-adjustmentRule.DaylightDelta.TotalMinutes; string timezoneStandardName = tzi.StandardName; string timezoneDaylightName = tzi.DaylightName; var l = new LoaderWrapper { ApplicationName = applicationName, CommandLine = commandLine, CurrentDirectory = currentDirectory, AnsiCodePage = ansiCodePage, OemCodePage = oemCodePage, LocaleID = localeID, DefaultCharset = defaultCharset, DefaultFaceName = defaultFaceName, TimezoneBias = timezoneBias, TimezoneDaylightBias = timezoneDaylightBias, TimezoneStandardName = timezoneStandardName, TimezoneDaylightName = timezoneDaylightName, DebugMode = debugMode, }; uint ret; if ((ret = l.Start()) != 0) { if (IsAdministrator()) { MessageBox.Show( String.Format( "Error number {0} detected.\r\n\r\nThis may because the target executable is a 64-bit binary which is not supported by the current version of Locale Emulator.", Convert.ToString(ret, 16).ToUpper()), "Locale Emulator"); } else { RunWithElevatedProcess(Args); } } } catch (Exception e) { MessageBox.Show(e.ToString()); } }
private static TimeZoneInfo RecreateZone(TimeZoneInfo zone) => TimeZoneInfo.CreateCustomTimeZone(zone.Id, zone.BaseUtcOffset, zone.DisplayName, zone.StandardName, zone.DisplayName, zone.GetAdjustmentRules());
internal TimeZoneInfoItem(string /*!*/ phpName, TimeZoneInfo /*!*/ info, string abbrevation, bool isAlias) { // alter the ID with php-like name if (!phpName.EqualsOrdinalIgnoreCase(info.Id)) { info = TimeZoneInfo.CreateCustomTimeZone(phpName, info.BaseUtcOffset, info.DisplayName, info.StandardName, info.DaylightName, info.GetAdjustmentRules()); } // this.PhpName = phpName; this.Info = info; this.Abbrevation = abbrevation; this.IsAlias = isAlias; }
private static bool ZoneRulesDontReferToLeapDays(TimeZoneInfo zone) => !zone.GetAdjustmentRules().Any(rule => TransitionRefersToLeapDay(rule.DaylightTransitionStart) || TransitionRefersToLeapDay(rule.DaylightTransitionEnd));
/// <summary> /// Creates a new <see cref="BclDateTimeZone" /> from a <see cref="TimeZoneInfo"/> from the Base Class Library. /// </summary> /// <param name="bclZone">The original time zone to take information from.</param> /// <returns>A <see cref="BclDateTimeZone"/> wrapping the given <c>TimeZoneInfo</c>.</returns> /// <exception cref="ArgumentNullException"><paramref name="bclZone"/> is null.</exception> public static BclDateTimeZone FromTimeZoneInfo(TimeZoneInfo bclZone) { Preconditions.CheckNotNull(bclZone, "bclZone"); Offset standardOffset = Offset.FromTimeSpan(bclZone.BaseUtcOffset); Offset minSavings = Offset.Zero; // Just in case we have negative savings! Offset maxSavings = Offset.Zero; var rules = bclZone.GetAdjustmentRules(); if (!bclZone.SupportsDaylightSavingTime || rules.Length == 0) { var fixedInterval = new ZoneInterval(bclZone.StandardName, Instant.MinValue, Instant.MaxValue, standardOffset, Offset.Zero); return(new BclDateTimeZone(bclZone, standardOffset, standardOffset, new FixedZoneIntervalMap(fixedInterval))); } var adjustmentIntervals = new List <AdjustmentInterval>(); var headInterval = ComputeHeadInterval(bclZone, rules[0]); Instant previousEnd = headInterval != null ? headInterval.End : Instant.MinValue; // TODO(Post-V1): Tidy this up. All of this is horrible. for (int i = 0; i < rules.Length; i++) { var rule = rules[i]; ZoneRecurrence standard, daylight; GetRecurrences(bclZone, rule, out standard, out daylight); minSavings = Offset.Min(minSavings, daylight.Savings); maxSavings = Offset.Max(maxSavings, daylight.Savings); // Find the last valid transition by working back from the end of time. It's safe to unconditionally // take the value here, as there must *be* some recurrences. var lastStandard = standard.PreviousOrFail(LastValidTick, standardOffset, daylight.Savings); var lastDaylight = daylight.PreviousOrFail(LastValidTick, standardOffset, Offset.Zero); bool standardIsLater = lastStandard.Instant > lastDaylight.Instant; Transition lastTransition = standardIsLater ? lastStandard : lastDaylight; Offset seamSavings = lastTransition.NewOffset - standardOffset; string seamName = standardIsLater ? bclZone.StandardName : bclZone.DaylightName; Instant nextStart; Instant ruleEnd = GetRuleEnd(rule, lastTransition); // Handle the final rule, which may or may not to extend to the end of time. If it doesn't, // we transition to standard time at the end of the rule. if (i == rules.Length - 1) { // If the final transition was to standard time, we can just treat the seam as going on forever. nextStart = standardIsLater ? Instant.MaxValue : ruleEnd; var seam = new ZoneInterval(seamName, lastTransition.Instant, nextStart, lastTransition.NewOffset, seamSavings); var adjustmentZone = new DaylightSavingsDateTimeZone("ignored", standardOffset, standard.ToInfinity(), daylight.ToInfinity()); adjustmentIntervals.Add(new AdjustmentInterval(previousEnd, adjustmentZone, seam)); previousEnd = nextStart; } else { // Handle one rule going into another. This is the cause of much pain, as there are several options: // 1) Going into a "normal" rule with two transitions per year. // 2) Going into a "single transition" rule, signified by a transition "into" the current offset // right at the start of the year. This is treated as if the on-the-edge transition doesn't exist. // // Additionally, there's the possibility that the offset at the start of the next rule (i.e. the // one before the first transition) isn't the same as the offset at the end of end of the current rule // (i.e. lastTransition.NewOffset). This only occurs for Namibia time as far as we've seen, but in that // case we create a seam which only goes until the end of this rule, then an extra zone interval for // the time between the start of the rule and the first transition, then we're as normal, starting at // the first transition. See bug 115 for a bit more information. var nextRule = rules[i + 1]; ZoneRecurrence nextStandard, nextDaylight; GetRecurrences(bclZone, nextRule, out nextStandard, out nextDaylight); // By using the seam's savings for *both* checks, we can detect "daylight to daylight" and // "standard to standard" transitions as happening at the very start of the rule. var firstStandard = nextStandard.NextOrFail(lastTransition.Instant, standardOffset, seamSavings); var firstDaylight = nextDaylight.NextOrFail(lastTransition.Instant, standardOffset, seamSavings); // Ignore any "right at the start of the rule" transitions. var firstStandardInstant = firstStandard.Instant == ruleEnd ? Instant.MaxValue : firstStandard.Instant; var firstDaylightInstant = firstDaylight.Instant == ruleEnd ? Instant.MaxValue : firstDaylight.Instant; bool firstStandardIsEarlier = firstStandardInstant < firstDaylightInstant; var firstTransition = firstStandardIsEarlier ? firstStandard : firstDaylight; nextStart = firstTransition.Instant; var seamEnd = nextStart; AdjustmentInterval startOfRuleExtraSeam = null; Offset previousOffset = firstStandardIsEarlier ? firstDaylight.NewOffset : firstStandard.NewOffset; if (previousOffset != lastTransition.NewOffset) { seamEnd = ruleEnd; // Recalculate the *real* transition, as we're now going from a different wall offset... var firstRule = firstStandardIsEarlier ? nextStandard : nextDaylight; nextStart = firstRule.NextOrFail(ruleEnd, standardOffset, previousOffset - standardOffset).Instant; var extraSeam = new ZoneInterval(firstStandardIsEarlier ? bclZone.DaylightName : bclZone.StandardName, ruleEnd, nextStart, previousOffset, previousOffset - standardOffset); // The extra adjustment interval is really just a single zone interval; we'll never need the DaylightSavingsDateTimeZone part. startOfRuleExtraSeam = new AdjustmentInterval(extraSeam.Start, null, extraSeam); } var seam = new ZoneInterval(seamName, lastTransition.Instant, seamEnd, lastTransition.NewOffset, seamSavings); var adjustmentZone = new DaylightSavingsDateTimeZone("ignored", standardOffset, standard.ToInfinity(), daylight.ToInfinity()); adjustmentIntervals.Add(new AdjustmentInterval(previousEnd, adjustmentZone, seam)); if (startOfRuleExtraSeam != null) { adjustmentIntervals.Add(startOfRuleExtraSeam); } previousEnd = nextStart; } } ZoneInterval tailInterval = previousEnd == Instant.MaxValue ? null : new ZoneInterval(bclZone.StandardName, previousEnd, Instant.MaxValue, standardOffset, Offset.Zero); IZoneIntervalMap uncachedMap = new BclZoneIntervalMap(adjustmentIntervals, headInterval, tailInterval); IZoneIntervalMap cachedMap = CachingZoneIntervalMap.CacheMap(uncachedMap, CachingZoneIntervalMap.CacheType.Hashtable); return(new BclDateTimeZone(bclZone, standardOffset + minSavings, standardOffset + maxSavings, cachedMap)); }
static void CompareTimeZoneData(TimeZone tz, TimeZoneInfo tzi, Java.Util.TimeZone jtz) { Console.WriteLine("## Comparing TimeZone Data:"); Console.WriteLine("# TimeZone: StandardName={0}; DaylightName={1}", tz.StandardName, tz.DaylightName); Console.WriteLine("# TimeZoneInfo: StandardName={0}; DaylightName={1}; DisplayName={2}; Id={3}", tzi.StandardName, tzi.DaylightName, tzi.DisplayName, tzi.Id); Console.WriteLine("# Java TimeZone: DisplayName={0}; ID={1}", jtz.DisplayName, jtz.ID); bool found_errors = false; for (int year = 2012; year < 2015; ++year) { if (tz != null) { var dst = tz.GetDaylightChanges(year); Console.WriteLine("Year: {0}; DST: {1} -> {2}", year, dst.Start.ToString("g"), dst.End.ToString("g")); } for (int month = 1; month <= 12; month++) { int lastDayInMonth = DateTime.DaysInMonth(year, month); for (int day = 1; day <= lastDayInMonth; day++) { var localtime = new DateTime(year, month, day, 10, 00, 00, DateTimeKind.Local); var utctime = localtime.ToUniversalTime(); var tz_offset = tz.GetUtcOffset(localtime); var tzi_offset = tzi.GetUtcOffset(localtime); var tz_dst = tz.IsDaylightSavingTime(localtime); var tzi_dst = tzi.IsDaylightSavingTime(localtime); using (var jd = ToDate(localtime)) { var jtz_dst = jtz.InDaylightTime(jd); var ms = (int)(localtime - new DateTime(year, month, day, 0, 0, 0, DateTimeKind.Local)).TotalMilliseconds; var jtz_offseti = jtz.GetOffset(1, year, month - 1, day, ((int)localtime.DayOfWeek) + 1, ms); var jtz_offset = TimeSpan.FromMilliseconds(jtz_offseti); if (tz_offset != tzi_offset || tz_offset != jtz_offset || tzi_offset != jtz_offset || tz_dst != tzi_dst || tz_dst != jtz_dst || tzi_dst != jtz_dst) { found_errors = true; Console.WriteLine("MISMATCH! @ {0} [{1}]", localtime, jd.ToLocaleString()); Console.WriteLine("\t TimeZone Offset: {0}", tz_offset); Console.WriteLine("\t TimeZoneInfo Offset: {0}", tzi_offset); Console.WriteLine("\tJava TimeZone Offset: {0}", jtz_offset); Console.WriteLine("\t TimeZone DST: {0}", tz_dst); Console.WriteLine("\t TimeZoneInfo DST: {0}", tzi_dst); Console.WriteLine("\t Java TimeZone DST: {0}", jtz_dst); } } } } } if (found_errors) { var rules = tzi.GetAdjustmentRules(); for (int i = 0; i < rules.Length; ++i) { var rule = rules [i]; Console.WriteLine("# AdjustmentRules[{0}]: DaylightDelta={1}; DateStart={2}; DateEnd={3}; DaylightTransitionStart={4}/{5} @ {6}; DaylightTransitionEnd={7}/{8} @ {9}", i, rule.DaylightDelta, rule.DateStart.ToString("yyyy-MM-dd"), rule.DateEnd.ToString("yyyy-MM-dd"), rule.DaylightTransitionStart.Month, rule.DaylightTransitionStart.Day, rule.DaylightTransitionStart.TimeOfDay.ToString("hh:mm:ss"), rule.DaylightTransitionEnd.Month, rule.DaylightTransitionEnd.Day, rule.DaylightTransitionEnd.TimeOfDay.ToString("hh:mm:ss")); } } Assert.IsFalse(found_errors, "TimeZoneData MISMATCH! See logcat output for details."); }
public static AdjustmentRule[] GetAdjustmentRulesEx(this TimeZoneInfo tz) { return(tz.GetAdjustmentRules().Select(y => new AdjustmentRule(y)).ToArray()); }
private static void DoRunWithLEProfile(string path, LEProfile profile) { try { if (profile.RunAsAdmin && !SystemHelper.IsAdministrator()) { ElevateProcess(); return; } if (profile.RunWithSuspend) { if (DialogResult.No == MessageBox.Show( "You are running a exectuable with CREATE_SUSPENDED flag.\r\n" + "\r\n" + "The exectuable will be executed after you click the \"Yes\" button, " + "But as a background process which has no notfications at all." + "You can attach it by using OllyDbg, or stop it with Task Manager.\r\n", "Locale Emulator Debug Mode Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Information )) { return; } } string applicationName = string.Empty; string commandLine = string.Empty; if (Path.GetExtension(path).ToLower() == ".exe") { applicationName = path; commandLine = path.StartsWith("\"") ? string.Format("{0} ", path) : String.Format("\"{0}\" ", path); commandLine += profile.Parameter; } else { string[] jb = AssociationReader.GetAssociatedProgram(Path.GetExtension(path)); if (jb == null) { return; } applicationName = jb[0]; commandLine = jb[0].StartsWith("\"") ? string.Format("{0} ", jb[0]) : String.Format("\"{0}\" ", jb[0]); commandLine += jb[1].Replace("%1", path).Replace("%*", profile.Parameter); } string currentDirectory = Path.GetDirectoryName(path); bool debugMode = profile.RunWithSuspend; var ansiCodePage = (uint)CultureInfo.GetCultureInfo(profile.Location).TextInfo.ANSICodePage; var oemCodePage = (uint)CultureInfo.GetCultureInfo(profile.Location).TextInfo.OEMCodePage; var localeID = (uint)CultureInfo.GetCultureInfo(profile.Location).TextInfo.LCID; var defaultCharset = (uint) GetCharsetFromANSICodepage(CultureInfo.GetCultureInfo(profile.Location) .TextInfo.ANSICodePage); TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById(profile.Timezone); var timezoneBias = (int)-tzi.BaseUtcOffset.TotalMinutes; TimeZoneInfo.AdjustmentRule[] adjustmentRules = tzi.GetAdjustmentRules(); TimeZoneInfo.AdjustmentRule adjustmentRule = null; if (adjustmentRules.Length > 0) { // Find the single record that encompasses today's date. If none exists, sets adjustmentRule to null. adjustmentRule = adjustmentRules.SingleOrDefault(ar => ar.DateStart <= DateTime.Now && DateTime.Now <= ar.DateEnd); } int timezoneDaylightBias = adjustmentRule == null ? 0 : (int)-adjustmentRule.DaylightDelta.TotalMinutes; string timezoneStandardName = tzi.StandardName; string timezoneDaylightName = tzi.DaylightName; LERegistryEntry[] registries = profile.RedirectRegistry ? new LERegistry().GetRegistryEntries() : new LERegistryEntry[0]; var l = new LoaderWrapper { ApplicationName = applicationName, CommandLine = commandLine, CurrentDirectory = currentDirectory, AnsiCodePage = ansiCodePage, OemCodePage = oemCodePage, LocaleID = localeID, DefaultCharset = defaultCharset, TimezoneBias = timezoneBias, TimezoneDaylightBias = timezoneDaylightBias, TimezoneStandardName = timezoneStandardName, TimezoneDaylightName = timezoneDaylightName, NumberOfRegistryRedirectionEntries = registries.Length, DebugMode = debugMode, }; registries.ToList() .ForEach( item => l.AddRegistryRedirectEntry(item.Root, item.Key, item.Name, item.Type, item.Data)); uint ret; if ((ret = l.Start()) != 0) { if (SystemHelper.IsAdministrator()) { MessageBox.Show(String.Format( "Launch failed.\r\n" + "\r\n" + "Commands: {0}\r\n" + "Error Number: {1}\r\n" + "Administrator: {2}\r\n" + "\r\n" + "If you have any antivirus software running, please turn it off and try again.\r\n" + "If you think this error is related to LE itself, feel free to submit an issue at\r\n" + "https://github.com/xupefei/Locale-Emulator/issues.\r\n" + "\r\n" + "\r\n" + "You can press CTRL+C to copy this message to your clipboard.\r\n", commandLine, Convert.ToString(ret, 16).ToUpper(), SystemHelper.IsAdministrator() ), "Locale Emulator Version " + GlobalHelper.GetLEVersion()); } else { ElevateProcess(); } } } catch (Exception e) { MessageBox.Show(e.ToString()); } }