diff --git a/src/MrGameEng.Core/Calendar.cs b/src/MrGameEng.Core/Calendar.cs
index b64fca8..f79a987 100644
--- a/src/MrGameEng.Core/Calendar.cs
+++ b/src/MrGameEng.Core/Calendar.cs
@@ -51,6 +51,15 @@ public sealed class Calendar
return (float)(days - Math.Floor(days));
}
}
+
+ /// Minutes elapsed in the current day, 0–1439 (a day is 24×60 in-game minutes).
+ public int MinuteOfDay => (int)(DayProgress * 1440f) % 1440;
+
+ /// Hour of the current day, 0–23.
+ public int Hour => MinuteOfDay / 60;
+
+ /// Minute of the current hour, 0–59.
+ public int Minute => MinuteOfDay % 60;
}
/// Wires the in-game calendar into the engine.
diff --git a/tests/MrGameEng.Core.Tests/CalendarTests.cs b/tests/MrGameEng.Core.Tests/CalendarTests.cs
index 43fcbb2..63b0fbd 100644
--- a/tests/MrGameEng.Core.Tests/CalendarTests.cs
+++ b/tests/MrGameEng.Core.Tests/CalendarTests.cs
@@ -41,6 +41,19 @@ public class CalendarTests
Assert.Equal(0.5f, calendar.DayProgress, 5);
}
+ [Fact]
+ public void HourAndMinute_DecomposeTimeOfDay()
+ {
+ var clock = new GameClock();
+ var calendar = new Calendar(clock, secondsPerDay: 1440f); // one minute per in-game minute
+
+ clock.Advance(14 * 60 + 30); // 14:30
+
+ Assert.Equal(14, calendar.Hour);
+ Assert.Equal(30, calendar.Minute);
+ Assert.Equal(14 * 60 + 30, calendar.MinuteOfDay);
+ }
+
[Fact]
public void Pause_DoesNotAdvanceTheCalendar()
{