I want to define the begin of a day in another timezone with .NET/C#.
Example:
My current timezone = GMT+1
so DateTime.Today returns 19/11/2009 23:00 UTC
but actually I want to get the DateTime.Today for timezone GMT+2 which would be 19/11/2009 22:00 UTC.
How do I do this without juggling with offsets & daylightsaving calculations?
You can use TimeZoneInfo.ConvertTime. This is new in .NET 3.5.
Try:
var zone = TimeZoneInfo.GetSystemTimeZones().First(tz => tz.StandardName == DesiredTimeZoneName);
Debug.WriteLine(new DateTimeOffset(DateTime.UtcNow.Date.Ticks, zone.BaseUtcOffset).ToUniversalTime());
AFAIK, there's no other way to do this.
Related
When I look about how to convert time to NodaTime, I find many posts but not a single straight answer about what I need.
I have:
- A DateTime object (DateTime myDateTime)
- An Olson timezone (var TZ = "America/Los_Angeles")
I want:
- A ZonedDateTime object (ZonedDateTime myZonedDateTime)
Ideally, I'm looking for some helper like:
var myZonedDateTime = ZonedDateTime.From(myDateTime, TZ);
but all the samples I see go through turning the date into a string and then parsing the string, which seems quite odd.
There is a ZonedDateTime.FromDateTimeOffset() method, but the offset and the TimeZone are different things since the TZ can handle daylight savings.
It sounds like you just want:
var local = LocalDateTime.FromDateTime(myDateTime);
var zone = DateTimeZoneProviders.Tzdb[id];
var zoned = local.InZoneLeniently(zone);
Except:
You may well want to write your own rules instead of using InZoneLeniently
You may want to use DateTimeZoneProviders.Tzdb.GetZoneOrNull(id) if you're not sure whether the zone ID will be recognized by Noda Time.
I have a date as string. There is no time info.
For eg. "20131031" ie) 31 oktober 2013.
I want to verify whether it is the date on which DST happens or not ?
w.r.t. WesternEurope.
ie) Does c# have an API, to say it is a DST date or not ?
I want simply a boolean as return, for the last sunday of October and last sunday of March.
which are the dates on which clocks are adjusted.
Per MSDN Documentation
Important
Whenever possible, use the TimeZoneInfo class instead of the TimeZone class.
You should consider TimeZone deprecated.
Instead, you can check DST for the local time zone like this:
DateTime dt = new DateTime(2013,10,31);
TimeZoneInfo tzi = TimeZoneInfo.Local;
bool isDST = tzi.IsDaylightSavingTime(dt);
For a specific time zone, do this instead:
DateTime dt = new DateTime(2013,10,31);
TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById("W. Europe Standard Time");
bool isDST = tzi.IsDaylightSavingTime(dt);
If you want to know when the daylight periods start and stop, you'll have to work through the transition rules from tzi.GetAdjustmentRules(). That can get a bit complex though. You would probably be better off using Noda Time for that.
You can use the TimeZone.IsDaylightSavingTime method, it takes a DateTime:
public virtual bool IsDaylightSavingTime(
DateTime time
)
So for example:
var tz = TimeZone.CurrentTimeZone;
var is_dst = tz.IsDaylightSavingTime(DateTime.Now);
See MSDN for more information.
Yes, there is an API: TimeZone.GetDaylightChanges
http://msdn.microsoft.com/en-us/library/system.timezone.getdaylightchanges.aspx
You provide a year and it will return a DaylightTime object, which contains the start and end dates for daylight saving. You can then compare your date against those two to determine if its a DLS date or not.
Whilst this answer has been accepted, please see Matt Johnson's answer below for details why it's not the best answer and why the TimeZoneInfo class should be used instead. https://stackoverflow.com/a/19523173/7122
I'm up against an issue storing datetimes as UTC and confused why this does not yield the same result when changing timezones:
var dt = DateTime.Parse("1/1/2013");
MessageBox.Show(TimeZoneInfo.ConvertTimeToUtc(dt, TimeZoneInfo.Local).ToString());
I am manually switching my local time zone on the machine between eastern and central.
Central yields 1/1/2013 6:00:00 AM, and Eastern yields 1/1/2013 5:00:00 AM. What am I missing here? They should be the same regardless of the time zone, correct?
Thanks so much in advance!
I think what you are missing is that the DateTime returned by your DateTime.Parse() statement doesn't come with a time zone. It's just a date and time that can be in any time zone. When you call TimeZoneInfo.ConvertTimeToUtc(dt, TimeZoneInfo.Local), you are telling it which time zone it starts in. So if you start in Central, you will get one answer, whereas if you start in Eastern, you will get an answer that is an hour earlier, UTC. Indeed, this is what your code shows.
There is a .ToUniversalTime() method for DateTime class
This is midnight
var dt = DateTime.Parse("1/1/2013");
Midnight in eastern and central is not the same absolute time.
That is the whole purpose of time zones.
You can use NodaTime :
static string LocalTimeToUTC(string timeZone, string localDateTime)
{
var pattern = LocalDateTimePattern.CreateWithInvariantCulture("dd/MM/yyyy HH:mm:ss");
LocalDateTime ldt = pattern.Parse(localDateTime).Value;
ZonedDateTime zdt = ldt.InZoneLeniently(DateTimeZoneProviders.Tzdb[timeZone]);
Instant instant = zdt.ToInstant();
ZonedDateTime utc = instant.InUtc();
string output = utc.ToString("dd/MM/yyyy HH:mm:ss", CultureInfo.InvariantCulture);
return output;
}
When you have trouble with converting to local time to UTC then just remove the last keyword of index and then convert to UtcDateTime
NewsDate = DateTimeOffset.Parse(data.NewsDate.Remove(data.NewsDate.LastIndexOf("IST"))).UtcDateTime;
How do I convert US-style DateTime such as 5/1/2012 3:38:27 PM returned from the server to user's local time? I am developing for windows phone.
I've tried
DateTime localTime = serverTime.ToLocalTime();
but the result is off a couple of hours. I thought ToLocalTime() will take care of the conversion to any timezone the user are in? Perhaps I need to get the user's timezone info first?
EDIT 1
I think the serverTime is in the PST time zone
EDIT 2
My timezone is GMT +8. I tried the following, but the resulting localTime is 15 hour behind.
TimeZoneInfo localZone = TimeZoneInfo.Local;
DateTime localTime = TimeZoneInfo.ConvertTime(serverTime, localZone);
EDIT 3
This result in 7 hours behind my local time.
TimeZoneInfo localZone = TimeZoneInfo.Local;
DateTime dateTimeKind = DateTime.SpecifyKind(serverTime, DateTimeKind.Utc);
DateTime localTime = TimeZoneInfo.ConvertTime(dateTimeKind, localZone);
EDIT 4
OK I think I am getting there but not sure if this is applicable for all time zones. I think I still have to consider day light saving because the resulting local time is just one hour ahead now.
TimeZoneInfo localZone = TimeZoneInfo.Local;
double offset = localZone.GetUtcOffset(DateTime.Now).TotalHours;
DateTime dateTimeKind = DateTime.SpecifyKind(serverTime, DateTimeKind.Utc);
DateTime localTime = TimeZoneInfo.ConvertTime(dateTimeKind, localZone).AddHours(offset);
But then how do you get DLS is in effect for a particular time zone in Windows Phone? TimeZoneInfo.FindSystemTimeZoneById does not seem to be supported?
For this to work, the DateTime-object serverTime must be of the UTC-form - or at least know what Kindit is. Read all the details around this under the remarks section of this page.
Best of luck!
What does the time represent? If it is a specific moment in time, such as the date and time that something happened, then you should update your server code to return the time in one of the following formats:
// ISO8601 local time with offset.
// get from DateTimeOffset.ToString("o")
2012-05-01T15:38:27-07:00
// ISO8601 UTC time
// get from DateTime.ToString("o") when kind is UTC
2012-05-01T22:38:27Z
It's really important that you do this, because local times can be ambiguous when daylight savings ends. You must either provide the correct offset, (-8 for PST, -7 for PDT), or send as UTC.
There are very few scenarios where sending local time by itself makes sense. If you think you have one, please elaborate about what the time represents.
I've got an asp.net application that must run some code every day at a specific time in the Eastern Time Zone (DST aware). So my first thought is, get the eastern time value and convert it to local server time.
So I need something like this:
var eastern = DateTime.Today.AddHours(17); // run at 5pm eastern
var timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
var utc = TimeZoneInfo.ConvertTimeToUtc(eastern, timeZoneInfo);
var local = TimeZoneInfo.ConvertTimeFromUtc(utc, TimeZoneInfo.Local);
But how do I specify that the eastern DateTime object should be in the EST timezone.
Am I approaching this the wrong way?
First, there are several things you have to consider. You have to deal with Daylight Savings Time, which from time to time seems to change (the start and end dates have changed twice in the last 10 years). So in the Northern Hemisphere Winter, Eastern time is -5 GMT (or UTC). But, in the Summer it's -6 GMT or is that -4 GMT, I can never keep it straight (nor should I have to).
There are some DNF library functions to deal with time zone information, however you really need .net 3.5 for the most useful stuff. There's the TimeZoneInfo class in .net 3.5.
TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
DateTime dt = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(DateTime.Now,
TimeZoneInfo.IsDaylightSavingsTime(tzi) ?
tzi.DaylightName : tzi.StandardName);
if (dt.Hour == 17)
....
Also, keep in mind that twice every year an hour is lost or gained, so you also have to account for that if, for example, you have a countdown timer you display "time until next processing" or something like that. The fact is, time handling is not as easy as it would seem at first thought, and there are a lot of edge cases.
Seems I was able to answer my own question. Here's the code I'm using to get a next-run DateTime object.
private DateTime GetNextRun()
{
var today = DateTime.Today;
var runTime = new DateTime(today.Year, today.Month, today.Day, 17, 0, 0);
var timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
var offset = timeZoneInfo.GetUtcOffset(runTime);
var dto = new DateTimeOffset(runTime, offset);
if (DateTime.Now > dto.LocalDateTime)
dto = dto.AddDays(1);
return dto.LocalDateTime;
}
Doing all the conversion using DateTimeOffset instead of DateTime proved effective. It even seems to handle Daylight Savings Time correctly.
A DateTime doesn't know about a time zone. Even DateTimeOffset doesn't really know about a time zone - it knows about a UTC instant and an offset from that.
You can write your own struct which does have a TimeZoneInfo and a DateTime, but I'm not sure you need it in this case. Are you just trying to schedule 5pm in Eastern time, or is this actually more general? What are you doing with the DateTime (or whatever) afterwards? Using DateTimeOffset and TimeZoneInfo you can definitely get the UTC instant of the time you're interested in; if you just need to know the time between "now" and then, that's fairly easy.
I feel duty-bound to point out that when Noda Time is production-ready, it would almost certainly be the right answer :)
You could use the DateTime.UtcNow to get UTC central time(which I believe is GMT 0) and from htere on just figure out how many time zones the one you want is and remove/add an hour for each zone.