Skip to content

Commit

Permalink
Support specifying a different timezone in Interval attribute
Browse files Browse the repository at this point in the history
  • Loading branch information
derekantrican committed Aug 22, 2024
1 parent 80b339e commit eaeb690
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 3 deletions.
2 changes: 1 addition & 1 deletion ClockworkFramework.Core/ClockworkFramework.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Version>6.4.0</Version>
<Version>6.5.0</Version>
</PropertyGroup>

<ItemGroup>
Expand Down
27 changes: 25 additions & 2 deletions ClockworkFramework.Core/Interval.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public class Interval
//Todo: simplify interval constructors somehow (and therefore: attribute)
//Todo: allow for "Interval.Once" to only run a task one time after startup

public Interval(TimeType timeType, int frequency, int hour, int minute)
public Interval(TimeType timeType, int frequency, int hour, int minute, string timezone = null)
{
if (timeType == TimeType.Week)
{
Expand All @@ -35,6 +35,7 @@ public Interval(TimeType timeType, int frequency, int hour, int minute)
Frequency = frequency;
Hour = hour;
Minute = minute;
Timezone = timezone;
}

public Interval(TimeType timeType, int frequency)
Expand All @@ -56,20 +57,22 @@ public Interval(TimeType timeType, int frequency)
Frequency = frequency;
}

public Interval(DayOfWeek dayOfWeek, int frequency, int hour, int minute)
public Interval(DayOfWeek dayOfWeek, int frequency, int hour, int minute, string timezone = null)
{
TimeType = TimeType.Week;
DayOfWeek = dayOfWeek;
Frequency = frequency;
Hour = hour;
Minute = minute;
Timezone = timezone;
}

public TimeType TimeType { get; }
public int Frequency { get; }
public DayOfWeek DayOfWeek { get; }
public int Hour { get; }
public int Minute { get; }
public string Timezone { get; }

public TimeSpan CalculateTimeToNext(DateTime fromDateTime)
{
Expand Down Expand Up @@ -130,6 +133,26 @@ public TimeSpan CalculateTimeToNext(DateTime fromDateTime)
throw new Exception("Unable to calculate next occurence");
}

if (!string.IsNullOrEmpty(Timezone))
{
try
{
//This is a rudimentary first version. Some potential problems that might arise,
//causing this to provide inaccurate results:
// - At the bottom, we attempt to account for DST changes, but by converting timezones,
// I wouldn't be surprised if there were multiple DST or similar changes in between
// - Etc. (Timezones can be VERY weird. This could fail in a variety of ways)

TimeZoneInfo timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(Timezone); //I could use https://github.com/mattjohnsonpint/TimeZoneConverter to support IANA timezones

next = TimeZoneInfo.ConvertTime(next.Value, timeZoneInfo);
}
catch (TimeZoneNotFoundException)
{
throw new Exception($"Unrecognized timezone '{Timezone}'");
}
}

//Using UTC converts here gives us the correct TimeSpan even if there is a DST change in between
return TimeZoneInfo.ConvertTimeToUtc(next.Value) - TimeZoneInfo.ConvertTimeToUtc(fromDateTime);
}
Expand Down
14 changes: 14 additions & 0 deletions ClockworkFramework.Core/IntervalAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,28 @@ public IntervalAttribute(TimeType timeType, int frequency)
Interval = new Interval(timeType, frequency);
}

//Interval for "run every # (Hour|Day|Month|etc) [at X time]"
public IntervalAttribute(TimeType timeType, int frequency, int hour, int minute)
{
Interval = new Interval(timeType, frequency, hour, minute);
}

//Interval for "run every # (Mon|Tues|Wed|etc) [at X time]"
public IntervalAttribute(DayOfWeek dayOfWeek, int frequency, int hour, int minute)
{
Interval = new Interval(dayOfWeek, frequency, hour, minute);
}

//Interval for "run every # (Hour|Day|Month|etc) [at X time]" WITH timezone (https://learn.microsoft.com/en-us/windows-hardware/manufacture/desktop/default-time-zones)
public IntervalAttribute(TimeType timeType, int frequency, int hour, int minute, string timezone)
{
Interval = new Interval(timeType, frequency, hour, minute, timezone);
}

//Interval for "run every # (Mon|Tues|Wed|etc) [at X time]" WITH timezone (https://learn.microsoft.com/en-us/windows-hardware/manufacture/desktop/default-time-zones)
public IntervalAttribute(DayOfWeek dayOfWeek, int frequency, int hour, int minute, string timezone)
{
Interval = new Interval(dayOfWeek, frequency, hour, minute, timezone);
}
}
}

0 comments on commit eaeb690

Please sign in to comment.