84 lines
3.2 KiB
C#
84 lines
3.2 KiB
C#
using Elternbeirat.Contracts;
|
||
using Elternbeirat.Web.Shared;
|
||
|
||
namespace Elternbeirat.Web.Features.Events;
|
||
|
||
/// <summary>
|
||
/// Formats the date range of an <see cref="Event"/> for display in German.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// Shared by the full event list and the home-page events embed, so both render
|
||
/// dates the same way.
|
||
/// <para>
|
||
/// This is the event counterpart to
|
||
/// <see cref="Posts.PostDateFormat"/>, which formats a plain
|
||
/// <see cref="DateOnly"/> day instead of a point-in-time range.
|
||
/// </para>
|
||
/// </remarks>
|
||
public static class EventDateFormat
|
||
{
|
||
/// <summary>
|
||
/// Date format for the start, and for a single-day event.
|
||
/// </summary>
|
||
private const string LongDate = "dddd, d. MMMM yyyy";
|
||
|
||
/// <summary>
|
||
/// Date format for the end of a multi-day event; the weekday is omitted.
|
||
/// </summary>
|
||
private const string ShortDate = "d. MMMM yyyy";
|
||
|
||
/// <summary>
|
||
/// Formats the date range of an event.
|
||
/// </summary>
|
||
/// <param name="event">
|
||
/// The event to format.
|
||
/// </param>
|
||
/// <returns>
|
||
/// The formatted range, depending on <see cref="Event.End"/> and <see cref="Event.HasTime"/>:
|
||
/// <list type="bullet">
|
||
/// <item>
|
||
/// <description>No end: <c>Donnerstag, 8. Oktober 2026, 19:30 Uhr</c></description>
|
||
/// </item>
|
||
/// <item>
|
||
/// <description>Same day: <c>Donnerstag, 8. Oktober 2026, 19:30–21:00 Uhr</c></description>
|
||
/// </item>
|
||
/// <item>
|
||
/// <description>Several days: <c>Freitag, 9. Oktober 2026 – 11. Oktober 2026</c></description>
|
||
/// </item>
|
||
/// </list>
|
||
/// Without a time, the time parts are omitted.
|
||
/// </returns>
|
||
public static string Range(Event @event)
|
||
=> (@event.Start, @event.End, @event.HasTime) switch
|
||
{
|
||
(var start, null, var hasTime)
|
||
=> Stamp(start, LongDate, hasTime),
|
||
(var start, { } end, true) when end.Date == start.Date
|
||
=> $"{start.ToString(LongDate, Cultures.German)}, {start.ToString("HH:mm", Cultures.German)}–{end.ToString("HH:mm", Cultures.German)} Uhr",
|
||
(var start, { } end, false) when end.Date == start.Date
|
||
=> Stamp(start, LongDate, withTime: false),
|
||
(var start, { } end, var hasTime)
|
||
=> $"{Stamp(start, LongDate, hasTime)} – {Stamp(end, ShortDate, hasTime)}",
|
||
};
|
||
|
||
/// <summary>
|
||
/// Formats a single point in time as a date with an optional time.
|
||
/// </summary>
|
||
/// <param name="value">
|
||
/// The date and time to format.
|
||
/// </param>
|
||
/// <param name="dateFormat">
|
||
/// The date format, e.g. <see cref="LongDate"/>.
|
||
/// </param>
|
||
/// <param name="withTime">
|
||
/// <see langword="true"/> to append the time, e.g. <c>, 19:30 Uhr</c>.
|
||
/// </param>
|
||
/// <returns>
|
||
/// The formatted date, with the time if requested.
|
||
/// </returns>
|
||
private static string Stamp(DateTime value, string dateFormat, bool withTime)
|
||
=> withTime
|
||
? value.ToString(dateFormat + ", HH:mm", Cultures.German) + " Uhr"
|
||
: value.ToString(dateFormat, Cultures.German);
|
||
}
|