Example #1
0
        public void ParseExactIncludingPreparse_Valid()
        {
            var pattern = OffsetPattern.CreateWithInvariantCulture("HH:mm");
            ParseResult <Offset> parseResult = pattern.Parse("12:34");

            parseResult.TryGetValue(default(Offset), out Offset result);
        }
Example #2
0
 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);
     }
 }
Example #3
0
        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);
            }
Example #5
0
        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);
Example #8
0
 static Parsing()
 {
     NoSignPattern          = OffsetPattern.CreateWithInvariantCulture("HH:mm");
     NoTimeSeparatorPattern = OffsetPattern.CreateWithInvariantCulture("-HHmm");
 }
Example #9
0
        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}**";
            }));
        }
Example #10
0
 public void ParsePattern_Valid()
 {
     OffsetPattern.CreateWithInvariantCulture("HH:mm");
 }
Example #11
0
 public OffsetBenchmarks()
 {
     offsetPattern = OffsetPattern.CreateWithInvariantCulture("HH:mm");
 }
Example #12
0
        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)}");
                        }
                    }
                }
            }
        }