the_lotus
the_lotus

Reputation: 12748

Hours in month, with daylight savings

Is there a built-in function to calculate the number of hours in a month? It needs it take care of daylightsaving (which add or reduce an hour).

Upvotes: 5

Views: 280

Answers (2)

SBFrancies
SBFrancies

Reputation: 4240

An alternative implementation in C# which allows the TimeZone to be specified:

public static int HoursInMonth(int year, int month, string timeZoneId)
{
    var timeZone = TimeZoneInfo.FindSystemTimeZoneById(timeZoneId);         
    var date = new DateTime(year, month, 1);
    var nextMonth = date.AddMonths(1);
    var start = TimeZoneInfo.ConvertTimeToUtc(date, timeZone);
    var end = TimeZoneInfo.ConvertTimeToUtc(nextMonth, timeZone);
    
    return (int)(end - start).TotalHours;   
}

Upvotes: 0

Jon Skeet
Jon Skeet

Reputation: 1500835

If you're not in a time zone where midnight isn't always valid, you could do something like this (apologies if the VB syntax is slightly off):

Dim start = New DateTime(year, month, day, 0, 0, 0, DateTimeKind.Local)
Dim end = start.AddMonths(1)
Dim length = end.ToUniversalTime() - start.ToUniversalTime()
Dim hours = length.TotalHours

That has a potential problem if you're somewhere like Brazil where the DST transition occurs at midnight local time. Note that the above is all assuming you want to use the system-local time zone.

With Noda Time, you could create the appropriate LocalDate values, then convert to a ZonedDateTime at the start of the relevant day, and work out the difference that way, without any ambiguity. C# example:

var zone = ... // Whatever DateTimeZone you want...
var start = new LocalDate(year, month, day);
var end = start.PlusMonths(1);
var startInstant = zone.AtStartOfDay(start).ToInstant();
var endInstant = zone.AtStartOfDay(end).ToInstant();
var duration = endInstant - startInstant;
var hours = duration.Ticks / NodaConstants.TicksPerHour;

Upvotes: 4

Related Questions