From 4f02fb27da9a7e7a655eb7e42557743e06d8eeb5 Mon Sep 17 00:00:00 2001 From: Sijmen Schoon Date: Sun, 4 Jul 2021 14:36:21 +0200 Subject: [PATCH] Parse DURATION property from iCal --- BlazorApp/Data/Calendar.cs | 58 +++++++++++++++++++++++++++++++++- BlazorApp/Pages/Calendar.razor | 4 +-- BlazorApp/Pages/Event.razor | 4 +-- 3 files changed, 61 insertions(+), 5 deletions(-) diff --git a/BlazorApp/Data/Calendar.cs b/BlazorApp/Data/Calendar.cs index bcc68ab..abafcb4 100644 --- a/BlazorApp/Data/Calendar.cs +++ b/BlazorApp/Data/Calendar.cs @@ -16,6 +16,17 @@ namespace BlazorApp.Data public DateTime? DtStart { get; set; } public DateTime? DtEnd { get; set; } public string Description { get; set; } + public TimeSpan? Duration { get; set; } + + public DateTime? CalculatedEnd + { + get + { + if (Duration != null) + return DtStart + Duration; + return DtEnd; + } + } } public class Calendar @@ -40,6 +51,48 @@ namespace BlazorApp.Data return DateTime.ParseExact(s, format, CultureInfo.InvariantCulture); } + /// + /// Very non-strict parser of durations as specified in + /// https://datatracker.ietf.org/doc/html/rfc5545#section-3.3.6 + /// + private static TimeSpan? _parseDuration(string s) + { + var timeSpan = new TimeSpan(); + var positive = s[0] != '-'; + var value = 0; + foreach (var c in s) + { + if (char.IsDigit(c)) + { + value = value * 10 + (c - '0'); + continue; + } + + switch (c) + { + case 'W': + timeSpan += TimeSpan.FromDays(value * 7); + break; + case 'D': + timeSpan += TimeSpan.FromDays(value); + break; + case 'H': + timeSpan += TimeSpan.FromHours(value); + break; + case 'M': + timeSpan += TimeSpan.FromMinutes(value); + break; + case 'S': + timeSpan += TimeSpan.FromSeconds(value); + break; + } + + value = 0; + } + + return positive ? timeSpan : -timeSpan; + } + private static List ParseICal(string iCal) { Event @event = null; @@ -108,6 +161,9 @@ namespace BlazorApp.Data case "DTEND": @event.DtEnd = _parseDateTime(value); break; + case "DURATION": + @event.Duration = _parseDuration(value); + break; } } @@ -122,7 +178,7 @@ namespace BlazorApp.Data var client = new HttpClient(); if (AuthorizationHeader != null) client.DefaultRequestHeaders.Add("Authorization", AuthorizationHeader); - + var body = await client.GetStringAsync(Url); var events = ParseICal(body); diff --git a/BlazorApp/Pages/Calendar.razor b/BlazorApp/Pages/Calendar.razor index ff79110..88c6a26 100644 --- a/BlazorApp/Pages/Calendar.razor +++ b/BlazorApp/Pages/Calendar.razor @@ -28,10 +28,10 @@ else } - @if (@event.DtEnd != null) + @if (@event.CalculatedEnd != null) {
- End: @(@event.DtEnd) + End: @(@event.CalculatedEnd)
} diff --git a/BlazorApp/Pages/Event.razor b/BlazorApp/Pages/Event.razor index 3782c1e..577a728 100644 --- a/BlazorApp/Pages/Event.razor +++ b/BlazorApp/Pages/Event.razor @@ -22,10 +22,10 @@ else } - @if (_event.DtEnd != null) + @if (_event.CalculatedEnd != null) {
- End: @_event.DtEnd + End: @_event.CalculatedEnd
}