A gas day is defined as a time range of 24 hours which starts at 5:00 UTC and ends at 5:00 UTC of the following day during the European standard time. During the European daylight saving time, it start at 4:00 UTC and ends at 4:00 UTC of the following day (see Wikipedia, or ACER for an English explanation).
I need to work with gas days in an application in order to do the following things:
- Get the current gas day for any given UTC timestamp. Example: "2022-03-22 05:00:00" (UTC) should become "2022-03-22 00:00:00" (gas day).
- Add and/or subtract a timespan (days, hours etc.) from a specific gas day to get a new timestamp which also takes DST into account. For example, this means that if I subtract 7 days from the timestamp "2022-03-29 04:00:00" (UTC) (which equals the gas day "2022-03-29), I want to get the timestamp "2022-03-22 05:00:00" (UTC).
This feels to me as if "gas day" should be available as something similar to a time zone which I can then work with in my application, but attempting to do this using DateTime
or DateTimeOffset
leaves me completely clueless about what I am supposed to do to make this work.
Could anyone point me into the right direction on what I have to do to allow me to do the calculations I explained above? Is there maybe a library which makes this a bit easier to do? I already looked into, for example, NodaTime, but I couldn't really find anything in its documentation that would make it easier for me to solve this task.
CodePudding user response:
Here is a quick solution that implements your logic for a gas day into a C# Extension Method attached to the System.DateTime
type. This can also be attached to DateTimeOffset
with similar logic if you want to use that type.
Here is the code:
public static class SpecialDateExtensions
{
public static DateTime GetGasDay(this DateTime current)
{
var datePart = current.Date;
var gasDayThreshold = datePart.AddHours(5);
return current > gasDayThreshold ? datePart : datePart.AddDays(-1);
}
}
static void Main(string[] args)
{
// usage
var now = DateTime.Now;
var gasday = now.GetGasDay();
}
CodePudding user response:
You can create a custom Time Zone that matches the rules of Gas Day.
Since the rules you mention are based off another time zone, it's easy enough to pull in the rules for the other time zone, and base yours off of that:
static TimeZoneInfo CreateGasDayTimezone()
{
// Use CET adjustment rules for daylight saving time
var cet = TimeZoneInfo.FindSystemTimeZoneById("Central Europe Standard Time");
var cetAdjustmentRules = cet.GetAdjustmentRules();
// Create a new timezone offset by 5 hours off UTC, using CET for DST
var gasday = TimeZoneInfo.CreateCustomTimeZone(
"Europe/Gas_Day",
TimeSpan.FromHours(-5),
"Gas Day",
"Gas Day (Standard)",
"Gas Day (Daylight)",
cetAdjustmentRules);
return gasday;
}
Using the new time zone is easy enough:
var date = new DateTime(2020, 1, 1);
var gasdayZone = CreateGasDayTimezone();
var dateAsGasDay = TimeZoneInfo.ConvertTimeFromUtc(date, gasdayZone);
Console.WriteLine(date " is " dateAsGasDay " in gas day");