How to tell if it's British Summer Time

2019-02-26 00:03发布

问题:

I have the following code, which should return an offset of 60 (to show that in the UK at present, we are in British Summer Time - ie. 60 minutes ahead of GMT):

var info = TimeZoneInfo.FindSystemTimeZoneById("Greenwich Standard Time");
DateTimeOffset localServerTime = DateTimeOffset.Now;
double off = localServerTime.Offset.TotalMinutes;
return off;

However, it returns 0.

Could anyone please help fix this for me?

回答1:

Use TimeZoneInfo.IsDaylightSavingTime Method (DateTimeOffset) to find if it is currently Daylight saving for your Timezone.

var info = TimeZoneInfo.FindSystemTimeZoneById("Greenwich Standard Time");
DateTimeOffset localServerTime = DateTimeOffset.Now;
bool isDaylightSaving = info.IsDaylightSavingTime(localServerTime);

There are further examples here



回答2:

Your machine is not configured correctly if you get 0 and live in the UK. Probable causes are:

  • The machine's time zone is not set correctly. Click the clock on the taskbar to correct.
  • The machine is not configured to observe daylight savings. Click the clock.
  • The database that TimeZoneInfo consults for daylight savings rules in out of date or corrupted. It is stored in the HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones registry key.

Be careful about making radical changes, having it configured wrong might well have been done intentionally to work around some kind of flaw in a business-critical app that runs on the server. Talk to whomever administers the server first.



回答3:

Another option is to use Noda Time.

The following code works with Noda Time 1.4 and higher:

var zone = NodaTime.TimeZones.TzdbDateTimeZoneSource.Default.ForId("Europe/London");
var zonedClock = NodaTime.SystemClock.Instance.InZone(zone);
var zonedDateTime = zonedClock.GetCurrentZonedDateTime();
bool isDST = zonedDateTime.IsDaylightSavingTime();
Console.WriteLine(isDST);
  • zone is a DateTimeZone object representing the UK's timezone, "Europe/London"
  • zonedClock is a ZonedClock object which represents, in this case, the system clock and the UK's timezone
  • zonedDateTime is a ZonedDateTime object representing the current date and time in the timezone ("the current instant provided by the underlying clock, adjusted to the time zone of this object")
  • isDST is a boolean indicating whether the current instant is in DST or not. At the time of writing (April 2018) this evaluates to true

With earlier versions of Noda where ZonedClock is not available, we can do this instead:

var zone = NodaTime.TimeZones.TzdbDateTimeZoneSource.Default.ForId("Europe/London");
var now = Instant.FromDateTimeOffset(DateTimeOffset.Now);
var zonedDateTime = new ZonedDateTime(now, zone);
bool isDST = zonedDateTime.IsDaylightSavingTime();


回答4:

To master conversion from one timezone to anther you need to see what's supported (how?) and what's not.

foreach (var tz in TimeZoneInfo.GetSystemTimeZones())
{
    Console.WriteLine("TimeZone Offset: {0} Name : {1}, Supports DLS: {2}", tz.BaseUtcOffset,tz.StandardName,tz.SupportsDaylightSavingTime);
}

This should give you the list all timezones including info about DayLightSaving. Notice that:

TimeZone Offset: 00:00:00 Name : Greenwich Standard Time, Supports DLS: False

TimeZone Offset: 00:00:00 Name : GMT Standard Time, Supports DLS: True

So you need to use "GMT Standard Time" because it supports daylight saving already. No work needs to be done.

Here is sample code:

private static string GetBSTTimeStamp(string timestamp)
{
    DateTime dt = DateTime.Parse(timestamp);
    //TimeZoneInfo bst = TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time");
    //Console.WriteLine("Time zone supports dls? {0}", bst.SupportsDaylightSavingTime);
    //Console.WriteLine("Time zone offset? {0}", bst.BaseUtcOffset);
    DateTime dateTimeInUtc = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(dt, "Eastern Standard Time", "GMT Standard Time");
    return dateTimeInUtc.ToString();
}