I have written a code which basically pulls out transactions from my DB in a PST time zone. What I'd like to do then is simply convert those dates into CEST time zone and IST (Israel Standard Time).
I did something like following :
var transactions = ctx.UserStores.Where(x => x.UserId == loggedUser.UserId).SelectMany(x => x.StoreItems.SelectMany(y => y.StoreItemTransactions)).ToList();
var hourlyData = transactions
.GroupBy(x => TimeZoneInfo.ConvertTime(x.TransactionDate.Value, TimeZoneInfo.FindSystemTimeZoneById(timeZone)).Hour)
.Select(pr => new HourlyGraph { Hour = pr.Key, Sales = pr.Sum(x => x.QuantitySoldTransaction) })
.ToList();
where timeZone parameter can be one of following:
Central European Standard Time
Israel Standard Time
Pacific Standard Time
Naurally when timeZone parameter is = PST I would expect the same results in my list... But the weird thing is the results get completely shuffled up and I'm not sure why ...
So the dates in my DB are kept in PST time zone and I'm trying to convert them into one of these 3 above time zones...
What am I doing wrong here??
Sample code that uses the version of TimeZoneInfo.ConvertTime which expects both a source and target timezone.
DateTime sourceTime = new DateTime(2015, 6, 10, 10, 20, 30, DateTimeKind.Unspecified);
TimeZoneInfo sourceTimeZone = TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time");
foreach(var targetTimeZoneID in new string[] { "Pacific Standard Time", "Israel Standard Time", "Central European Standard Time" })
{
TimeZoneInfo targetTimeZone = TimeZoneInfo.FindSystemTimeZoneById(targetTimeZoneID);
var converted = TimeZoneInfo.ConvertTime(sourceTime, sourceTimeZone, targetTimeZone);
Console.WriteLine("{0}: {1:yyyy-MM-dd HH:mm:ss}", targetTimeZoneID, converted);
}
Console.ReadLine();
Output is:
Pacific Standard Time: 2015-06-10 10:20:30 Israel Standard Time:
2015-06-10 20:20:30 Central European Standard Time: 2015-06-10
19:20:30
Related
I need to create a DateTime with a set date and time which will be in a specific time zone(West Asia Standard Time, W. Europe Standard Time etc).
DST must be preserved, so offset is out because for half of the year for a given time zone it will be for example +2h and for the other half +3h.
Then I want to convert the date to UTC.
I tried to do it in such a way that I could add this timezone offset later. However, firstly I do not like this solution and I am afraid that I will lose one hour when the time changes twice a year, and secondly I get an error:
"The UTC Offset for Utc DateTime instances must be 0."
var testTime = new DateTime(testDate.Year, testDate.Month, testDate.Day, 4, 0, 0, DateTimeKind.Utc);
var timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("West Asia Standard Time");
var timezoneTime = TimeZoneInfo.ConvertTimeFromUtc(runTime, timeZoneInfo);
var offset = timeZoneInfo.GetUtcOffset(timezoneTime);
I would like to get this kind of code
var timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("West Asia Standard Time");
var testTime = new DateTime(testDate.Year, testDate.Month, testDate.Day, 4, 0, 0, timeZoneInfo);
var utcTime = testTime.ToUniversalTime();
So, to sum up, I want to have method, where I pass year, month, day, hour, minute and timeZone and in return I will get DateTime that is in UTC
In javascript there are libraries, where the given time zone is given as a parameter but I have to do it on the server side.
You'd basically need TimeZoneInfo.ConvertTimeToUtc method.
Just make sure the Kind property of the passed DateTime is Unspecified, otherwise the method has special expectations for the sourceTimeZone argument and will throw exception.
e.g.
var testTime = new DateTime(testDate.Year, testDate.Month, testDate.Day, 4, 0, 0);
var timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("West Asia Standard Time");
var utcTime = TimeZoneInfo.ConvertTimeToUtc(testTime, timeZoneInfo);;
I am getting this error:
The supplied DateTime represents an invalid time. For example, when
the clock is adjusted forward, any time in the period that is skipped
is invalid
when I try to convert time 2020-03-29 02:30 from Eastern European Time (GMT+2) to UTC time.
According to this site the clock should change at 03:00 for Finland, which means that time 02:30 should be possible to convert to UTC.
But when I run the following code, an exception is thrown.
var timezoneMap = TimeZoneInfo.GetSystemTimeZones().ToDictionary(x => x.Id, x => x);
var timezoneInfo = timezoneMap["E. Europe Standard Time"];
var localTime1 = DateTime.SpecifyKind(new DateTime(2020, 12, 15, 0, 0, 0), DateTimeKind.Unspecified);
var localTime2 = DateTime.SpecifyKind(new DateTime(2020, 3, 29, 2, 30, 0), DateTimeKind.Unspecified);
var utc1 = TimeZoneInfo.ConvertTimeToUtc(localTime1, timezoneInfo); // 2020-12-14 22:00 correct
var utc2 = TimeZoneInfo.ConvertTimeToUtc(localTime2, timezoneInfo); // throws exception
What is wrong with the second conversion, why is there an exception?
The site you're looking at uses the IANA time zone data, which I believe to be accurate.
But your code uses the Windows time zone database, which in this case looks like it has a discrepancy... it seems to think that the transition is at midnight UTC rather than 1am UTC. Here's code to demonstrate that:
using System;
using System.Globalization;
class Program
{
static void Main()
{
var zone = TimeZoneInfo.FindSystemTimeZoneById("E. Europe Standard Time");
// Start at 2020-03-28T23:00Z - definitely before the transition
var utc = new DateTime(2020, 3, 28, 23, 0, 0, DateTimeKind.Utc);
for (int i = 0; i < 8; i++)
{
var local = TimeZoneInfo.ConvertTime(utc, zone);
Console.WriteLine($"{utc:yyyy-MM-dd HH:mm} UTC => {local:yyyy-MM-dd HH:mm} local");
utc = utc.AddMinutes(30);
}
}
}
Output (annotated):
2020-03-28 23:00 UTC => 2020-03-29 01:00 local
2020-03-28 23:30 UTC => 2020-03-29 01:30 local
2020-03-29 00:00 UTC => 2020-03-29 03:00 local <= Note the change here, at midnight UTC
2020-03-29 00:30 UTC => 2020-03-29 03:30 local
2020-03-29 01:00 UTC => 2020-03-29 04:00 local
2020-03-29 01:30 UTC => 2020-03-29 04:30 local
2020-03-29 02:00 UTC => 2020-03-29 05:00 local
2020-03-29 02:30 UTC => 2020-03-29 05:30 local
The current IANA data definitely does say 1am UTC, as shown in this line of the rules. So I believe the web site is correctly interpreting the data, and it's just a matter of the Windows time zone database being "different" (and, I suspect, incorrect).
I need to ALWAYS stamp my DB with Pacific Time, regardless if it's August or February.
Pacific Time is, the actual US west coast time at anytime of the year:
During Daylight saving times PT = PDT (Pacific Daylight time) = UTC - 7
During Non Daylight saving times PT = PST (Pacific Standard Time 0 = UTC - 8
I am using C# and do the following:
TimeZoneInfo pacificZone = TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time");
CreatedDate = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, pacificZone);
Would that automatically take into account Daylight saving times, or do I need to account for this by doing this:
TimeZoneInfo pacificZone = TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time");
CreatedDate = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, pacificZone);
if (!TimeZoneInfo.Local.IsDaylightSavingTime(CreatedDate))
{
CreatedDate = CreatedDate.AddHours(-1);
}
Is my first or 2nd code snippet the correct one?
The first block is the correct one.
Test code
var utcDateDuringDaylightSavingsTime = new DateTime(2018, 7, 1, 15, 30, 30, DateTimeKind.Utc);
TimeZoneInfo pacificZone = TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time");
var localDateDuringDaylightSavingsTime = TimeZoneInfo.ConvertTimeFromUtc(utcDateDuringDaylightSavingsTime, pacificZone);
var localDateNotDuringDaylightSavingsTime = TimeZoneInfo.ConvertTimeFromUtc(utcDateDuringDaylightSavingsTime.AddMonths(5), pacificZone);
Console.WriteLine(utcDateDuringDaylightSavingsTime.ToString("o") + "\t\tUTC");
Console.WriteLine(localDateDuringDaylightSavingsTime.ToString("o") + "\t\t Local during daylight saving");
Console.WriteLine(localDateNotDuringDaylightSavingsTime.ToString("o") + "\t\t Local not during daylight saving");
Output
2018-07-01T15:30:30.0000000Z UTC
2018-07-01T08:30:30.0000000 Local during daylight saving
2018-12-01T07:30:30.0000000 Local not during daylight saving
I have a variable with date time which I have to set on a specific date by these rukles and scenarios:
The API that I connect to has a daily limit and once that limit is reached I have to wait until NEXT DAY until 9:10 AM CEST <= This is very important
So I've been simply doing this:
var localTime = TimeZoneInfo.ConvertTime(DateTime.Now, TimeZoneInfo.FindSystemTimeZoneById("Central European Standard Time"));
var tomorrowAt0910 = localTime.AddDays(1).Date + new TimeSpan(9, 10, 0);
And I have realized that this code has a bug, because I can have following scenarios:
Let's say my application would expire on 30th of July at 15:00 PM in which case this logic up there would be VALID
BUT
We have a next following scenario which is more likely to happen:
Application expires on 31st of July 5:00 AM, in which case this logic is faulty because RENEWAL DATE will be set to 1st of August 9:10AM WHICH IS BAD
If the application expires in this second case, I should set the date to same day and few hours difference (from 5AM to 9AM)
How could I do this?
It sounds like what you really want is to say:
Find the current time in Central Europe
Find 9:10am on the same date
If 9:10am is after the current time, add a day
So something like:
// No need to do this more than once
private static readonly TimeZoneInfo centralEuropeZone =
TimeZoneInfo.FindSystemTimeZoneById("Central European Standard Time")
private static DateTime GetUtcResetTime()
{
// Using UtcNow to make it clear that the system time zone is irrelevant
var centralEuropeNow = TimeZoneInfo.ConvertTime(DateTime.UtcNow, centralEuropeZone);
var centralEuropeResetTime = centralEuropeNow.Date + new TimeSpan(9, 10, 0);
if (centralEuropeResetTime <= centralEuropeNow)
{
centralEuropeResetTime = centralEuropeResetTime.AddDays(1);
}
return TimeZoneInfo.ConvertTimeToUtc(centralEuropeResetTime, centralEuropeZone);
}
I've made that return a UTC DateTime so that no other code needs to worry about which zone it's in.
Check if the expire date is less that the current date, if so add one day.
DateTime expireDate = new DateTime(2018, 7, 30, 22, 0, 0); //for testing
DateTime tomorrowAt0910 = DateTime.Now.Date.AddHours(9).AddMinutes(10);
if (expireDate.Date < DateTime.Now.Date)
{
tomorrowAt0910.AddDays(1);
}
I'm facing an issue while converting dates between my server and client where both is running in Germany. The Regional settings on the client machines could be set to both UK or Germany.I recieve a date from the server which is CET format, and I need to represent this time on UI as UK time. For example a time recieved from server like say, 01/07/2010 01:00:00 should be represented on the UI as 01/07/2010 00:00:00. I have written a converter for this purpose, however while running it 'am getting a time difference of 2 hours.Below is the code, please can you help?
public class LocalToGmtConverter : IDateConverter
{
private readonly TimeZoneInfo timeZoneInfo;
public LocalToGmtConverter()
: this(TimeZoneInfo.Local)
{
}
public LocalToGmtConverter(TimeZoneInfo timeZoneInfo)
{
this.timeZoneInfo = timeZoneInfo;
}
public DateTime Convert(DateTime localDate)
{
var utcKind = DateTime.SpecifyKind(localDate, DateTimeKind.Utc);
return utcKind;
}
public DateTime ConvertBack(object fromServer)
{
DateTime serverDate = (DateTime)fromServer;
var utcOffset = timeZoneInfo.GetUtcOffset(serverDate);
var uiTime = serverDate- utcOffset;
return uiTime;
}
}
I think you're converting to UTC (instead of UK) time. Since there is still summer time in Central Europe (event if the temperatures say otherwise), the difference is +2 hours until October, 31st.
If you know that you're converting from Germany to UK (i.e. CEST to BST in summer and CET to GMT in winter), why you don't just subtract 1 hour?
If you want the time zone information for UK, you can construct it using
var britishZone = TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time");
Then you could convert the date using
var newDate = TimeZoneInfo.ConvertTime(serverDate, TimeZoneInfo.Local, britishZone);
This is what I do:
var BritishZone = TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time");
DateTime dt = DateTime.SpecifyKind(DateTime.UtcNow, DateTimeKind.Unspecified);
DateTime DateTimeInBritishLocal = TimeZoneInfo.ConvertTime(dt, TimeZoneInfo.Utc, BritishZone);
I needed to add the SpecifyKind part or the ConvertTime throws an exception
Use TimeZoneInfo.ConvertTime to convert original input timezone (CET) to target timezone (UK).
public static DateTime ConvertTime(
DateTime dateTime,
TimeZoneInfo sourceTimeZone,
TimeZoneInfo destinationTimeZone
)
Full guidance on MSDN here:
Converting Times Between Time Zones
Modified code sample from MSDN:
DateTime ceTime = new DateTime(2007, 02, 01, 08, 00, 00);
try
{
TimeZoneInfo ceZone = TimeZoneInfo.FindSystemTimeZoneById("Central Europe Standard Time");
TimeZoneInfo gmtZone = TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time");
Console.WriteLine("{0} {1} is {2} GMT time.",
ceTime,
ceZone.IsDaylightSavingTime(ceTime) ? ceZone.DaylightName : ceZone.StandardName,
TimeZoneInfo.ConvertTime(ceTime, ceZone, gmtZone));
}
catch (TimeZoneNotFoundException)
{
Console.WriteLine("The registry does not define the required timezones.");
}
catch (InvalidTimeZoneException)
{
Console.WriteLine("Registry data on the required timezones has been corrupted.");
}
The better approach to deal with local times is store them in unified representation such as UTC.
So you can convert all input times to UTC (via .ToUniversalTime()), and store (or transmit) its value. When you need to show it just convert back by using .ToLocalTime().
So you avoid rquirements to know which time zone was original value and can easily show stored value in different timezones.
Also you can avoid incoming troubles where you have to write specific logic for processing time in next timezone trying to figure out how to convert them amongs all available.
I realize the question is for C#, but if all you want to do is a single conversion you can do this from the PowerShell command line:
$d = [DateTime]::Parse("04/02/2014 17:00:00")
$gmt = [TimeZoneInfo]::FindSystemTimeZoneById("GMT Standard Time");
[TimeZoneInfo]::ConvertTime($d, $gmt, [TimeZoneInfo]::Local)
This script would convert 17:00 UK time into your local time zone.
For me, that would be CST. It's interesting to note that if I had set the date to 03/27/2014, the result would be different because the UK daylight saving time kicks in on different dates that the US.