Parse DURATION property from iCal

This commit is contained in:
Sijmen 2021-07-04 14:36:21 +02:00
parent 5f452c026e
commit 4f02fb27da
Signed by: vijfhoek
GPG Key ID: DAF7821E067D9C48
3 changed files with 61 additions and 5 deletions

View File

@ -16,6 +16,17 @@ namespace BlazorApp.Data
public DateTime? DtStart { get; set; } public DateTime? DtStart { get; set; }
public DateTime? DtEnd { get; set; } public DateTime? DtEnd { get; set; }
public string Description { 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 public class Calendar
@ -40,6 +51,48 @@ namespace BlazorApp.Data
return DateTime.ParseExact(s, format, CultureInfo.InvariantCulture); return DateTime.ParseExact(s, format, CultureInfo.InvariantCulture);
} }
/// <summary>
/// Very non-strict parser of durations as specified in
/// https://datatracker.ietf.org/doc/html/rfc5545#section-3.3.6
/// </summary>
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<Event> ParseICal(string iCal) private static List<Event> ParseICal(string iCal)
{ {
Event @event = null; Event @event = null;
@ -108,6 +161,9 @@ namespace BlazorApp.Data
case "DTEND": case "DTEND":
@event.DtEnd = _parseDateTime(value); @event.DtEnd = _parseDateTime(value);
break; break;
case "DURATION":
@event.Duration = _parseDuration(value);
break;
} }
} }
@ -122,7 +178,7 @@ namespace BlazorApp.Data
var client = new HttpClient(); var client = new HttpClient();
if (AuthorizationHeader != null) if (AuthorizationHeader != null)
client.DefaultRequestHeaders.Add("Authorization", AuthorizationHeader); client.DefaultRequestHeaders.Add("Authorization", AuthorizationHeader);
var body = await client.GetStringAsync(Url); var body = await client.GetStringAsync(Url);
var events = ParseICal(body); var events = ParseICal(body);

View File

@ -28,10 +28,10 @@ else
</div> </div>
} }
@if (@event.DtEnd != null) @if (@event.CalculatedEnd != null)
{ {
<div> <div>
<strong>End:</strong> @(@event.DtEnd) <strong>End:</strong> @(@event.CalculatedEnd)
</div> </div>
} }

View File

@ -22,10 +22,10 @@ else
</div> </div>
} }
@if (_event.DtEnd != null) @if (_event.CalculatedEnd != null)
{ {
<div> <div>
<strong>End:</strong> @_event.DtEnd <strong>End:</strong> @_event.CalculatedEnd
</div> </div>
} }