Parse DURATION property from iCal
This commit is contained in:
parent
5f452c026e
commit
4f02fb27da
3 changed files with 61 additions and 5 deletions
|
@ -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);
|
||||
}
|
||||
|
||||
/// <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)
|
||||
{
|
||||
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);
|
||||
|
||||
|
|
|
@ -28,10 +28,10 @@ else
|
|||
</div>
|
||||
}
|
||||
|
||||
@if (@event.DtEnd != null)
|
||||
@if (@event.CalculatedEnd != null)
|
||||
{
|
||||
<div>
|
||||
<strong>End:</strong> @(@event.DtEnd)
|
||||
<strong>End:</strong> @(@event.CalculatedEnd)
|
||||
</div>
|
||||
}
|
||||
|
||||
|
|
|
@ -22,10 +22,10 @@ else
|
|||
</div>
|
||||
}
|
||||
|
||||
@if (_event.DtEnd != null)
|
||||
@if (_event.CalculatedEnd != null)
|
||||
{
|
||||
<div>
|
||||
<strong>End:</strong> @_event.DtEnd
|
||||
<strong>End:</strong> @_event.CalculatedEnd
|
||||
</div>
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue