System.TimeZoneInfo.ParseTZBuffer C# (CSharp) Method

ParseTZBuffer() private static method

private static ParseTZBuffer ( string id, byte buffer, int length ) : TimeZoneInfo
id string
buffer byte
length int
return TimeZoneInfo
		private static TimeZoneInfo ParseTZBuffer (string id, byte [] buffer, int length)
		{
			//Reading the header. 4 bytes for magic, 16 are reserved
			int ttisgmtcnt = ReadBigEndianInt32 (buffer, 20);
			int ttisstdcnt = ReadBigEndianInt32 (buffer, 24);
			int leapcnt = ReadBigEndianInt32 (buffer, 28);
			int timecnt = ReadBigEndianInt32 (buffer, 32);
			int typecnt = ReadBigEndianInt32 (buffer, 36);
			int charcnt = ReadBigEndianInt32 (buffer, 40);

			if (length < 44 + timecnt * 5 + typecnt * 6 + charcnt + leapcnt * 8 + ttisstdcnt + ttisgmtcnt)
				throw new InvalidTimeZoneException ();

			Dictionary<int, string> abbreviations = ParseAbbreviations (buffer, 44 + 4 * timecnt + timecnt + 6 * typecnt, charcnt);
			Dictionary<int, TimeType> time_types = ParseTimesTypes (buffer, 44 + 4 * timecnt + timecnt, typecnt, abbreviations);
			List<KeyValuePair<DateTime, TimeType>> transitions = ParseTransitions (buffer, 44, timecnt, time_types);

			if (time_types.Count == 0)
				throw new InvalidTimeZoneException ();

			if (time_types.Count == 1 && time_types[0].IsDst)
				throw new InvalidTimeZoneException ();

			TimeSpan baseUtcOffset = new TimeSpan (0);
			TimeSpan dstDelta = new TimeSpan (0);
			string standardDisplayName = null;
			string daylightDisplayName = null;
			bool dst_observed = false;
			DateTime dst_start = DateTime.MinValue;
			List<AdjustmentRule> adjustmentRules = new List<AdjustmentRule> ();
			bool storeTransition = false;

			for (int i = 0; i < transitions.Count; i++) {
				var pair = transitions [i];
				DateTime ttime = pair.Key;
				TimeType ttype = pair.Value;
				if (!ttype.IsDst) {
					if (standardDisplayName != ttype.Name)
						standardDisplayName = ttype.Name;
					if (baseUtcOffset.TotalSeconds != ttype.Offset) {
						baseUtcOffset = new TimeSpan (0, 0, ttype.Offset);
						if (adjustmentRules.Count > 0) // We ignore AdjustmentRules but store transitions.
							storeTransition = true;
						adjustmentRules = new List<AdjustmentRule> ();
						dst_observed = false;
					}
					if (dst_observed) {
						//FIXME: check additional fields for this:
						//most of the transitions are expressed in GMT 
						dst_start += baseUtcOffset;
						DateTime dst_end = ttime + baseUtcOffset + dstDelta;

						//some weird timezone (America/Phoenix) have end dates on Jan 1st
						if (dst_end.Date == new DateTime (dst_end.Year, 1, 1) && dst_end.Year > dst_start.Year)
							dst_end -= new TimeSpan (24, 0, 0);

						/*
						 * AdjustmentRule specifies a DST period that starts and ends within a year.
						 * When we have a DST period longer than a year, the generated AdjustmentRule may not be usable.
						 * Thus we fallback to the transitions.
						 */
						if (dst_start.AddYears (1) < dst_end)
							storeTransition = true;

						DateTime dateStart, dateEnd;
						if (dst_start.Month < 7)
							dateStart = new DateTime (dst_start.Year, 1, 1);
						else
							dateStart = new DateTime (dst_start.Year, 7, 1);

						if (dst_end.Month >= 7)
							dateEnd = new DateTime (dst_end.Year, 12, 31);
						else
							dateEnd = new DateTime (dst_end.Year, 6, 30);

						
						TransitionTime transition_start = TransitionTime.CreateFixedDateRule (new DateTime (1, 1, 1) + dst_start.TimeOfDay, dst_start.Month, dst_start.Day);
						TransitionTime transition_end = TransitionTime.CreateFixedDateRule (new DateTime (1, 1, 1) + dst_end.TimeOfDay, dst_end.Month, dst_end.Day);
						if  (transition_start != transition_end) //y, that happened in Argentina in 1943-1946
							adjustmentRules.Add (AdjustmentRule.CreateAdjustmentRule (dateStart, dateEnd, dstDelta, transition_start, transition_end));
					}
					dst_observed = false;
				} else {
					if (daylightDisplayName != ttype.Name)
						daylightDisplayName = ttype.Name;
					if (dstDelta.TotalSeconds != ttype.Offset - baseUtcOffset.TotalSeconds) {
						// Round to nearest minute, since it's not possible to create an adjustment rule
						// with sub-minute precision ("The TimeSpan parameter cannot be specified more precisely than whole minutes.")
						// This happens for instance with Europe/Dublin, which had an offset of 34 minutes and 39 seconds in 1916.
						dstDelta = new TimeSpan (0, 0, ttype.Offset) - baseUtcOffset;
						if (dstDelta.Ticks % TimeSpan.TicksPerMinute != 0)
							dstDelta = TimeSpan.FromMinutes ((long) (dstDelta.TotalMinutes + 0.5f));
					}

					dst_start = ttime;
					dst_observed = true;
				}
			}

			TimeZoneInfo tz;
			if (adjustmentRules.Count == 0 && !storeTransition) {
				if (standardDisplayName == null) {
					var t = time_types [0];
					standardDisplayName = t.Name;
					baseUtcOffset = new TimeSpan (0, 0, t.Offset);
				}
				tz = CreateCustomTimeZone (id, baseUtcOffset, id, standardDisplayName);
			} else {
				tz = CreateCustomTimeZone (id, baseUtcOffset, id, standardDisplayName, daylightDisplayName, ValidateRules (adjustmentRules).ToArray ());
			}

			if (storeTransition && transitions.Count > 0) {
				tz.transitions = transitions;
				tz.supportsDaylightSavingTime = true;
			}

			return tz;
		}

Usage Example

Esempio n. 1
0
 static TimeZoneInfo _GetTimeZone(string id, string name)
 {
     if (db == null)
     {
         return(null);
     }
     byte[] buffer = db.GetTimeZoneData(name);
     if (buffer == null)
     {
         return(null);
     }
     return(TimeZoneInfo.ParseTZBuffer(id, buffer, buffer.Length));
 }
All Usage Examples Of System.TimeZoneInfo::ParseTZBuffer