public void ParseExactIncludingPreparse_Valid() { var pattern = OffsetPattern.CreateWithInvariantCulture("HH:mm"); ParseResult <Offset> parseResult = pattern.Parse("12:34"); parseResult.TryGetValue(default(Offset), out Offset result); }
public void CreateWithCurrentCulture() { using (CultureSaver.SetCultures(Cultures.DotTimeSeparator)) { var pattern = OffsetPattern.CreateWithCurrentCulture("H:mm"); var text = pattern.Format(Offset.FromHoursAndMinutes(1, 30)); Assert.AreEqual("1.30", text); } }
public void NumberFormatIgnored() { var culture = (CultureInfo)Cultures.EnUs.Clone(); culture.NumberFormat.PositiveSign = "P"; culture.NumberFormat.NegativeSign = "N"; var pattern = OffsetPattern.Create("+HH:mm", culture); Assert.AreEqual("+05:00", pattern.Format(Offset.FromHours(5))); Assert.AreEqual("-05:00", pattern.Format(Offset.FromHours(-5))); }
public void Should_return_local_time_with_specified_value_and_offset_utc_offset_string(string timeZoneId, string unixTimeSecondsKey) { var localTimeExpected = Instant.FromUnixTimeSeconds(_unixTimeSecondsUtc[unixTimeSecondsKey]).InZone(DateTimeZoneProviders.Tzdb[timeZoneId]); var localTimeOutcome = LocalTime.Create((ulong)_unixTimeSecondsUtc[unixTimeSecondsKey], timeZoneId); Assert.Equal(localTimeExpected.ToDateTimeUnspecified(), localTimeOutcome.Value); Assert.Equal($"{OffsetPattern.CreateWithInvariantCulture("-H").Format(localTimeExpected.Offset)}{(double.Parse(OffsetPattern.CreateWithInvariantCulture("%m").Format(localTimeExpected.Offset)) / 60).ToString("#.0#", CultureInfo.InvariantCulture)}", localTimeOutcome.UtcOffset); }
public void WritePoints(List <TimeSeriesPoint> points) { var timeSeriesIdentifier = CreateTimeSeriesIdentifier(); var csvPath = Directory.Exists(Context.SaveCsvPath) ? Path.Combine(Context.SaveCsvPath, SanitizeFilename($"{timeSeriesIdentifier.Identifier}.{CreatePeriod(Context.SourceQueryFrom, Context.SourceQueryTo)}.csv")) : Context.SaveCsvPath; Log.Info($"Saving {points.Count} extracted points to '{csvPath}' ..."); var dir = Path.GetDirectoryName(csvPath); if (!string.IsNullOrEmpty(dir)) { Directory.CreateDirectory(dir); } using (var writer = new StreamWriter(csvPath)) { var offsetPattern = OffsetPattern.CreateWithInvariantCulture("m"); var utcOffsetText = $"UTC{offsetPattern.Format(Context.UtcOffset ?? Offset.Zero)}"; var period = CreatePeriod(Context.SourceQueryFrom ?? Instant.MinValue, Context.SourceQueryTo ?? Instant.MaxValue); writer.WriteLine($"# {Path.GetFileName(csvPath)} generated by {Context.ExecutingFileVersion}"); writer.WriteLine($"#"); writer.WriteLine($"# Time series identifier: {timeSeriesIdentifier.Identifier}"); writer.WriteLine($"# Location: {timeSeriesIdentifier.LocationIdentifier}"); writer.WriteLine($"# UTC offset: ({utcOffsetText})"); writer.WriteLine($"# Value units: {Context.Unit}"); writer.WriteLine($"# Value parameter: {timeSeriesIdentifier.Parameter}"); writer.WriteLine($"# Interpolation type: {Context.InterpolationType}"); writer.WriteLine($"# Time series type: {Context.TimeSeriesType}"); writer.WriteLine($"#"); writer.WriteLine($"# Export options: Corrected signal from {period.StartText} to {period.EndText}"); writer.WriteLine($"#"); writer.WriteLine($"# CSV data starts at line 15."); writer.WriteLine($"#"); writer.WriteLine($"ISO 8601 UTC, Value, Grade, Qualifiers"); foreach (var point in points) { var time = point.Time ?? Instant.MinValue; writer.WriteLine($"{InstantPattern.ExtendedIsoPattern.Format(time)}, {point.Value:G12}, {point.GradeCode}, {FormatQualifiers(point.Qualifiers)}"); } } }
internal override IPartialPattern <Offset> CreatePartialPattern() => OffsetPattern.CreateWithInvariantCulture(Pattern).WithCulture(Culture).UnderlyingPattern;
internal override IPattern <Offset> CreatePattern() => OffsetPattern.CreateWithInvariantCulture(Pattern) .WithCulture(Culture);
static Parsing() { NoSignPattern = OffsetPattern.CreateWithInvariantCulture("HH:mm"); NoTimeSeparatorPattern = OffsetPattern.CreateWithInvariantCulture("-HHmm"); }
public async Task <DateTimeZone> FindTimeZone(Context ctx, string zoneStr) { // First, if we're given a flag emoji, we extract the flag emoji code from it. zoneStr = PluralKit.Utils.ExtractCountryFlag(zoneStr) ?? zoneStr; // Then, we find all *locations* matching either the given country code or the country name. var locations = TzdbDateTimeZoneSource.Default.Zone1970Locations; var matchingLocations = locations.Where(l => l.Countries.Any(c => string.Equals(c.Code, zoneStr, StringComparison.InvariantCultureIgnoreCase) || string.Equals(c.Name, zoneStr, StringComparison.InvariantCultureIgnoreCase))); // Then, we find all (unique) time zone IDs that match. var matchingZones = matchingLocations.Select(l => DateTimeZoneProviders.Tzdb.GetZoneOrNull(l.ZoneId)) .Distinct().ToList(); // If the set of matching zones is empty (ie. we didn't find anything), we try a few other things. if (matchingZones.Count == 0) { // First, we try to just find the time zone given directly and return that. var givenZone = DateTimeZoneProviders.Tzdb.GetZoneOrNull(zoneStr); if (givenZone != null) { return(givenZone); } // If we didn't find anything there either, we try parsing the string as an offset, then // find all possible zones that match that offset. For an offset like UTC+2, this doesn't *quite* // work, since there are 57(!) matching zones (as of 2019-06-13) - but for less populated time zones // this could work nicely. var inputWithoutUtc = zoneStr.Replace("UTC", "").Replace("GMT", ""); var res = OffsetPattern.CreateWithInvariantCulture("+H").Parse(inputWithoutUtc); if (!res.Success) { res = OffsetPattern.CreateWithInvariantCulture("+H:mm").Parse(inputWithoutUtc); } // If *this* didn't parse correctly, f**k it, bail. if (!res.Success) { return(null); } var offset = res.Value; // To try to reduce the count, we go by locations from the 1970+ database instead of just the full database // This elides regions that have been identical since 1970, omitting small distinctions due to Ancient History(tm). var allZones = TzdbDateTimeZoneSource.Default.Zone1970Locations.Select(l => l.ZoneId).Distinct(); matchingZones = allZones.Select(z => DateTimeZoneProviders.Tzdb.GetZoneOrNull(z)) .Where(z => z.GetUtcOffset(SystemClock.Instance.GetCurrentInstant()) == offset).ToList(); } // If we have a list of viable time zones, we ask the user which is correct. // If we only have one, return that one. if (matchingZones.Count == 1) { return(matchingZones.First()); } // Otherwise, prompt and return! return(await ctx.Choose("There were multiple matches for your time zone query. Please select the region that matches you the closest:", matchingZones, z => { if (TzdbDateTimeZoneSource.Default.Aliases.Contains(z.Id)) { return $"**{z.Id}**, {string.Join(", ", TzdbDateTimeZoneSource.Default.Aliases[z.Id])}"; } return $"**{z.Id}**"; })); }
public void ParsePattern_Valid() { OffsetPattern.CreateWithInvariantCulture("HH:mm"); }
public OffsetBenchmarks() { offsetPattern = OffsetPattern.CreateWithInvariantCulture("HH:mm"); }
public void WritePoints(List <TimeSeriesPoint> points, List <TimeSeriesNote> notes) { var timeSeriesIdentifier = CreateTimeSeriesIdentifier(); var csvPath = Directory.Exists(Context.SaveCsvPath) ? Path.Combine(Context.SaveCsvPath, SanitizeFilename($"{timeSeriesIdentifier.Identifier}.{CreatePeriod(Context.SourceQueryFrom, Context.SourceQueryTo)}.csv")) : Context.SaveCsvPath; Log.Info($"Saving {PointSummarizer.Summarize(points, "extracted point")} to '{csvPath}' ..."); var dir = Path.GetDirectoryName(csvPath); if (!string.IsNullOrEmpty(dir)) { Directory.CreateDirectory(dir); } var publishNotes = notes .Select(Convert) .ToList(); var notesLookup = new MetadataLookup <PublishNote>(publishNotes); using (var writer = new StreamWriter(csvPath)) { var offsetPattern = OffsetPattern.CreateWithInvariantCulture("m"); var utcOffsetText = $"UTC{offsetPattern.Format(Context.UtcOffset ?? Offset.Zero)}"; var period = CreatePeriod(Context.SourceQueryFrom ?? Instant.MinValue, Context.SourceQueryTo ?? Instant.MaxValue); writer.WriteLine($"# {Path.GetFileName(csvPath)} generated by {Context.ExecutingFileVersion}"); writer.WriteLine($"#"); writer.WriteLine($"# Time series identifier: {timeSeriesIdentifier.Identifier}"); writer.WriteLine($"# Location: {timeSeriesIdentifier.LocationIdentifier}"); writer.WriteLine($"# UTC offset: ({utcOffsetText})"); writer.WriteLine($"# Value units: {Context.Unit}"); writer.WriteLine($"# Value parameter: {timeSeriesIdentifier.Parameter}"); writer.WriteLine($"# Interpolation type: {Context.InterpolationType}"); writer.WriteLine($"# Time series type: {Context.TimeSeriesType}"); writer.WriteLine($"#"); writer.WriteLine($"# Export options: Corrected signal from {period.StartText} to {period.EndText}"); writer.WriteLine($"#"); writer.WriteLine($"# CSV data starts at line 15."); writer.WriteLine($"#"); var optionalNotesHeader = Context.SaveNotesMode == SaveNotesMode.WithPoints ? ", Notes" : string.Empty; writer.WriteLine($"ISO 8601 UTC, Value, Grade, Qualifiers{optionalNotesHeader}"); foreach (var point in points) { var time = point.Time ?? Instant.MinValue; var line = $"{InstantPattern.ExtendedIso.Format(time)}, {point.Value:G12}, {point.GradeCode}, {FormatQualifiers(point.Qualifiers)}"; if (Context.SaveNotesMode == SaveNotesMode.WithPoints) { var pointNotes = string.Join("\r\n", notesLookup.GetMany(time.ToDateTimeOffset()).Select(note => note.NoteText)); line += $", {CsvEscapedColumn(pointNotes)}"; } writer.WriteLine(line); } if (Context.SaveNotesMode == SaveNotesMode.SeparateCsv) { var notesCsvPath = Path.ChangeExtension(csvPath, ".Notes.csv"); Log.Info($"Saving {"extracted note".ToQuantity(notes.Count)} to '{notesCsvPath}' ..."); // ReSharper disable once AssignNullToNotNullAttribute using (var notesWriter = new StreamWriter(notesCsvPath)) { notesWriter.WriteLine($"# {Path.GetFileName(notesCsvPath)} generated by {Context.ExecutingFileVersion}"); notesWriter.WriteLine($"#"); notesWriter.WriteLine($"# Time series identifier: {timeSeriesIdentifier.Identifier}"); notesWriter.WriteLine($"# Location: {timeSeriesIdentifier.LocationIdentifier}"); notesWriter.WriteLine($"# UTC offset: ({utcOffsetText})"); notesWriter.WriteLine($"#"); notesWriter.WriteLine($"# Export options: Corrected signal notes from {period.StartText} to {period.EndText}"); notesWriter.WriteLine($"#"); notesWriter.WriteLine($"# CSV data starts at line 11."); notesWriter.WriteLine($"#"); notesWriter.WriteLine($"StartTime, EndTime, NoteText"); foreach (var note in notes) { if (!note.TimeRange.HasValue) { continue; } notesWriter.WriteLine($"{InstantPattern.ExtendedIso.Format(note.TimeRange.Value.Start)}, {InstantPattern.ExtendedIso.Format(note.TimeRange.Value.End)}, {CsvEscapedColumn(note.NoteText)}"); } } } } }