private void checkForUpdate(String localVersion) { if (System.Diagnostics.Debugger.IsAttached && File.Exists(tzdbFilename)) { return; } log.Debug("Checking for new timezone database..."); String nodatimeURL = "http://nodatime.org/tzdb/latest.txt"; String html = ""; System.Net.WebClient wc = new System.Net.WebClient(); wc.Headers.Add("user-agent", Settings.Instance.Proxy.BrowserUserAgent); try { html = wc.DownloadString(nodatimeURL); } catch (System.Exception ex) { log.Error("Failed to get latest NodaTime db version."); OGCSexception.Analyse(ex); return; } if (string.IsNullOrEmpty(html)) { log.Warn("Empty response from " + nodatimeURL); } else { html = html.TrimEnd('\r', '\n'); if (html.EndsWith(localVersion + ".nzd")) { log.Debug("Already have latest TZDB version."); } else { Regex rgx = new Regex(@"https*:.*/tzdb(.*)\.nzd$", RegexOptions.IgnoreCase); MatchCollection matches = rgx.Matches(html); if (matches.Count > 0) { String remoteVersion = matches[0].Result("$1"); if (string.Compare(localVersion, remoteVersion, System.StringComparison.InvariantCultureIgnoreCase) < 0) { log.Debug("There is a new version " + remoteVersion); try { wc.DownloadFile(html, tzdbFilename); log.Debug("New TZDB version downloaded - disposing of reference to old db data."); instance = null; } catch (System.Exception ex) { log.Error("Failed to download new TZDB database from " + html); OGCSexception.Analyse(ex); } } } else { log.Warn("Regex to extract latest version is no longer working!"); } } } }
private DateTime WindowsTimeZone(EventDateTime time) { DateTime theDate = DateTime.Parse(time.DateTime ?? time.Date); if (time.TimeZone == null) { return(theDate); } LocalDateTime local = new LocalDateTime(theDate.Year, theDate.Month, theDate.Day, theDate.Hour, theDate.Minute); DateTimeZone zone = DateTimeZoneProviders.Tzdb[TimezoneDB.FixAlexa(time.TimeZone)]; ZonedDateTime zonedTime = local.InZoneLeniently(zone); DateTime zonedUTC = zonedTime.ToDateTimeUtc(); log.Fine("IANA Timezone \"" + time.TimeZone + "\" mapped to \"" + zone.Id.ToString() + "\" with a UTC of " + zonedUTC.ToString("dd/MM/yyyy HH:mm:ss")); return(zonedUTC); }
private Microsoft.Office.Interop.Outlook.TimeZone WindowsTimeZone(string ianaZoneId) { ianaZoneId = TimezoneDB.FixAlexa(ianaZoneId); Microsoft.Office.Interop.Outlook.TimeZones tzs = oApp.TimeZones; var utcZones = new[] { "Etc/UTC", "Etc/UCT", "UTC", "Etc/GMT" }; if (utcZones.Contains(ianaZoneId, StringComparer.OrdinalIgnoreCase)) { log.Fine("Timezone \"" + ianaZoneId + "\" mapped to \"UTC\""); return(tzs["UTC"]); } NodaTime.TimeZones.TzdbDateTimeZoneSource tzDBsource = TimezoneDB.Instance.Source; // resolve any link, since the CLDR doesn't necessarily use canonical IDs var links = tzDBsource.CanonicalIdMap .Where(x => x.Value.Equals(ianaZoneId, StringComparison.OrdinalIgnoreCase)) .Select(x => x.Key); // resolve canonical zones, and include original zone as well var possibleZones = tzDBsource.CanonicalIdMap.ContainsKey(ianaZoneId) ? links.Concat(new[] { tzDBsource.CanonicalIdMap[ianaZoneId], ianaZoneId }) : links; // map the windows zone var mappings = tzDBsource.WindowsMapping.MapZones; var item = mappings.FirstOrDefault(x => x.TzdbIds.Any(possibleZones.Contains)); if (item == null) { throw new System.ApplicationException("Timezone \"" + ianaZoneId + "\" has no mapping."); } log.Fine("Timezone \"" + ianaZoneId + "\" mapped to \"" + item.WindowsId + "\""); return(tzs[item.WindowsId]); }
private void buildOutlookPattern(Event ev, AppointmentItem ai, out RecurrencePattern oPattern) { if (ev.Recurrence == null) { oPattern = null; return; } Dictionary <String, String> ruleBook = explodeRrule(ev.Recurrence); if (ruleBook == null) { throw new ApplicationException("WARNING: The recurrence pattern is not compatible with Outlook. This event cannot be synced."); } log.Fine("Building Outlook recurrence pattern"); oPattern = ai.GetRecurrencePattern(); #region RECURRENCE PATTERN //RRULE:FREQ=WEEKLY;UNTIL=20150906T000000Z;BYDAY=SA switch (ruleBook["FREQ"]) { case "DAILY": { oPattern.RecurrenceType = OlRecurrenceType.olRecursDaily; break; } case "WEEKLY": { oPattern.RecurrenceType = OlRecurrenceType.olRecursWeekly; // Need to work out dayMask from "BY" pattern // Eg "BYDAY=MO,TU,WE,TH,FR" OlDaysOfWeek dowMask = getDOWmask(ruleBook); if (dowMask != 0) { oPattern.DayOfWeekMask = dowMask; } break; } case "MONTHLY": { oPattern.RecurrenceType = OlRecurrenceType.olRecursMonthly; if (ruleBook.ContainsKey("BYSETPOS")) { oPattern.RecurrenceType = OlRecurrenceType.olRecursMonthNth; int gInstance = Convert.ToInt16(ruleBook["BYSETPOS"]); oPattern.Instance = (gInstance == -1) ? 5 : gInstance; oPattern.DayOfWeekMask = getDOWmask(ruleBook); if (oPattern.DayOfWeekMask == (OlDaysOfWeek)127 && gInstance == -1 && (ev.Start.DateTime ?? DateTime.Parse(ev.Start.Date)).Day > 28) { //In Outlook this is simply a monthly recurring oPattern.RecurrenceType = OlRecurrenceType.olRecursMonthly; } } if (ruleBook.ContainsKey("BYDAY")) { if (ruleBook["BYDAY"].StartsWith("-1")) { oPattern.RecurrenceType = OlRecurrenceType.olRecursMonthNth; oPattern.Instance = 5; oPattern.DayOfWeekMask = getDOWmask(ruleBook["BYDAY"].TrimStart("-1".ToCharArray())); } else if ("1,2,3,4".Contains(ruleBook["BYDAY"].Substring(0, 1))) { oPattern.RecurrenceType = OlRecurrenceType.olRecursMonthNth; oPattern.Instance = Convert.ToInt16(ruleBook["BYDAY"].Substring(0, 1)); oPattern.DayOfWeekMask = getDOWmask(ruleBook["BYDAY"].TrimStart(oPattern.Instance.ToString().ToCharArray())); } } break; } case "YEARLY": { oPattern.RecurrenceType = OlRecurrenceType.olRecursYearly; //Google interval is years, Outlook is months if (ruleBook.ContainsKey("INTERVAL") && Convert.ToInt16(ruleBook["INTERVAL"]) > 1) { oPattern.Interval = Convert.ToInt16(ruleBook["INTERVAL"]) * 12; } if (ruleBook.ContainsKey("BYSETPOS")) { oPattern.RecurrenceType = OlRecurrenceType.olRecursYearNth; int gInstance = Convert.ToInt16(ruleBook["BYSETPOS"]); oPattern.Instance = (gInstance == -1) ? 5 : gInstance; oPattern.DayOfWeekMask = getDOWmask(ruleBook); if (ruleBook.ContainsKey("BYMONTH")) { oPattern.MonthOfYear = Convert.ToInt16(ruleBook["BYMONTH"]); } } break; } } #endregion #region RANGE ai = OutlookOgcs.Calendar.Instance.IOutlook.WindowsTimeZone_set(ai, ev); oPattern.PatternStartDate = ev.Start.DateTime ?? DateTime.Parse(ev.Start.Date); if (ruleBook.ContainsKey("INTERVAL") && Convert.ToInt16(ruleBook["INTERVAL"]) > 1 && ruleBook["FREQ"] != "YEARLY") { oPattern.Interval = Convert.ToInt16(ruleBook["INTERVAL"]); } if (ruleBook.ContainsKey("COUNT")) { oPattern.Occurrences = Convert.ToInt16(ruleBook["COUNT"]); } if (ruleBook.ContainsKey("UNTIL")) { if (ruleBook["UNTIL"].StartsWith("4500")) { log.Warn("Outlook can't handle end dates this far in the future. Converting to no end date."); oPattern.NoEndDate = true; } else { DateTime endDate; if (ruleBook["UNTIL"].Length == 8 && !ruleBook["UNTIL"].EndsWith("Z")) { endDate = DateTime.ParseExact(ruleBook["UNTIL"], "yyyyMMdd", System.Globalization.CultureInfo.InvariantCulture).Date; } else { endDate = DateTime.ParseExact(ruleBook["UNTIL"], "yyyyMMddTHHmmssZ", System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.AdjustToUniversal); endDate = endDate.AddHours(TimezoneDB.GetUtcOffset(ev.End.TimeZone)).Date; } if (endDate < oPattern.PatternStartDate) { log.Debug("PatternStartDate: " + oPattern.PatternStartDate.ToString("yyyyMMddHHmmss")); log.Debug("PatternEndDate: " + ruleBook["UNTIL"].ToString()); String summary = GoogleOgcs.Calendar.GetEventSummary(ev, onlyIfNotVerbose: true); Forms.Main.Instance.Console.Update(summary + "The recurring Google event has an end date <i>before</i> the start date, which Outlook doesn't allow.<br/>" + "The synced Outlook recurrence has been changed to a single occurrence.", Console.Markup.warning); oPattern.Occurrences = 1; } else { oPattern.PatternEndDate = endDate; } } } if (!ruleBook.ContainsKey("COUNT") && !ruleBook.ContainsKey("UNTIL")) { oPattern.NoEndDate = true; } #endregion }