Get eastern time in c# without converting local time - c#

I know there are bunch of solutions on converting timezone to timezone, but what I'd like to know whether we can get eastern time without making conversion from our local time.

Well yes and no, if you represent using GMT always then you don't need to convert until you need to show locality.
Time is always in GMT and services should run under the GMT Timezone because of this reason among others.
Receiving and Storing a time in anything other than GMT / UTC requires conversions.
Please note the Timezone of the server should also be set to GMT for things to work as I indicated.
When you set things up like this it thus becomes much easier to reference and compare times and dates in different calendar date formats also.
This is the reason why DateTime offset made its way into the framework and sql server. if not careful when the Timezone on a server changes so does all stored and loaded dates in local format.
A date comparison is a date comparison. DateTime just wraps a memory structure which is defined in ticks and makes methods to access commonly used parts of the memory e.g. day or year or Time or TimeOfDay etc.
Furthermore conversion is only possible if you know both the source and destination offsets and then the calculation is always as given is given by -1 * (sourceOffset - destOffset)
Where the part in parenthesis represents the time zone difference.

Where the DateTime you want to convert is in UTC and called theDate
DateTime eastern = TimeZoneInfo
.ConvertTimeFromUtc(
theDate,
TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time"))
If theDate has a Kind of Local this will throw, only accepting Kind values of Utc or Unspecified. Of course, moving from local to UTC is easy and we could even check and do this conversion when required, but since you say you want this conversion "without making conversion from our local time" I'm assuming you have your times in UTC and hence having the exception would be better as it would warn you that times that should be UTC are being treat as local and a bug could pop up elsewhere.
This will use Eastern Daylight Time when theDate is a time when EDT is in effect, as that is the normal rule for EST. To use EST even when it is the summer you can create your own TimeZoneInfo:
TimeZoneInfo
.ConvertTimeFromUtc(
theDate,
TimeZoneInfo.CreateCustomTimeZone(
"Eastern Standard Time No Daylight Savings",
new TimeSpan(-5, 0, 0),
"Eastern Standard Time No Daylight Savings",
"Eastern Standard Time No Daylight Savings"))

Related

Get time zone with UTC conversion

I have the system date in BST . I want to convert it to UTC. So did the below:
string utcDate= TimeZoneInfo.ConvertTimeToUtc(dt).ToString("dd/MM/yyyy HH:mm:ss");
What I want is to get the zone along with the Date in UTC. Pls consider the daylight savings.
Example: 2019-07-08T23:59:00+01:00.
A few things:
The string format you gave the example of, 2019-07-08T23:59:00+01:00 is part of the ISO 8601 specification. To be precise, it is the "complete date and time of day representation" of the "ISO 8601 Extended Format". It also the format defined by RFC 3339.
In this format, the date and time portion represent the local time, as denoted by the time zone offset portion. In other words, the values are not in UTC, but already adjusted. In your example, 2019-07-08T23:59:00 is the local time and UTC+01:00 is in effect at that time. The corresponding UTC time would thus be an hour earlier, 2019-07-08T22:59:00Z.
You seem to be asking for the date in UTC but with an offset that includes daylight saving time. That is impossible, as UTC does not observe daylight saving time. The offset from UTC is always zero. You can read more about UTC here.
The offset of UTC itself is denoted with Z, but can also be represented with +00:00, which can be thought of as "zero offset from UTC". In other words, if you are referring to UTC time use the Z, and if you are referring to a local time that is aligned to UTC (such as GMT in London in the winter, or Iceland, etc.) use +00:00.
In your question, you say you want the system time in UTC with the offset. I will assume by "system time" you mean the current time of the clock on the system. That is provided by DateTime.UtcNow or DateTimeOffset.UtcNow. These return either a DateTime or DateTimeOffset structure - not a string. Since you wanted a string in a specific format, then you should first ask for the current time, and then format it as a string with ToString:
using System.Globalization;
...
string a = DateTime.UtcNow.ToString("yyyy-MM-dd'T'HH:mm:ssK", CultureInfo.InvariantCulture);
// output example: "2019-07-08T22:59:00Z"
string b = DateTimeOffset.UtcNow.ToString("yyyy-MM-dd'T'HH:mm:sszzz", CultureInfo.InvariantCulture);
// output example: "2019-07-08T22:59:00+00:00"
If what you actually wanted was the local time, such that the offset would be +00:00 in the winter and +01:00 in the summer (in the UK), then use Now instead of UtcNow. This gives the local time in the time zone of the computer where the code is running.
string c = DateTime.Now.ToString("yyyy-MM-dd'T'HH:mm:ssK", CultureInfo.InvariantCulture);
// output example: "2019-07-08T23:59:00+01:00"
string d = DateTimeOffset.Now.ToString("yyyy-MM-dd'T'HH:mm:sszzz", CultureInfo.InvariantCulture);
// output example: "2019-07-08T23:59:00+01:00"
If you actually wanted the time in the UK regardless of what the time zone of the local computer was on, then you'd have to first get the UTC time and then convert it to UK time before creating the string.
TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time");
string e = TimeZoneInfo.ConvertTime(DateTime.UtcNow, tzi).ToString("yyyy-MM-dd'T'HH:mm:ssK", CultureInfo.InvariantCulture);
// output example: "2019-07-08T23:59:00"
string f = TimeZoneInfo.ConvertTime(DateTimeOffset.UtcNow, tzi).ToString("yyyy-MM-dd'T'HH:mm:sszzz", CultureInfo.InvariantCulture);
// output example: "2019-07-08T23:59:00+01:00"
In example e, note that a DateTime can't store an arbitrary offset as the result of time zone conversion, and thus you get DateTimeKind.Unspecified assigned to the Kind property, which results in no offset being in the string representation. Thus most of the time you should use a DateTimeOffset (example f) instead.
Also, note the time zone ID of "GMT Standard Time" is the correct ID to use for the UK on Windows platforms. It correctly switches between GMT and BST when appropriate. If you are running .NET Core on non-Windows platforms (Linux, OSX, etc.), then you should use "Europe/London" instead. Or if you are wanting to write code that is platform-neutral then you can use my TimeZoneConverter library, which allows you to provide either form and run on any platform.
In your code example, you didn't call any of the "now" functions, but gave a dt variable. Assuming this is a DateTime, the result of calling TimeZoneInfo.ConvertTimeToUtc will depend on the Kind property of that variable. If it's DateTimeKind.Utc, then no conversion is performed. If it's DateTimeKind.Local or DateTimeKind.Unspecified, then the value is converted from the computer's local time zone to UTC.
Lastly, keep in mind that when talking to an international audience, time zone abbreviations can be ambiguous. I could deduce by "BST" that you meant British Summer Time, but only because you showed a +01:00 offset in your question. "BST" can also stand for "Bangladesh Standard Time" (+06:00), or "Bougainville Standard Time" (+11:00).
I guess you can do something like this:
var dt = DateTime.Now;
string utcDate = dt.ToUniversalTime().ToString("dd/MM/yyyy HH:mm:ss") +
dt.ToString(" zzz");
Output: (I'm in EET)
14/07/2019 20:02:17 +02:00
But be aware that this could be confusing to people. The standard way is that the timezone follows the local date, not the universal date.

c# parse string (without timezone) to DateTime, taking DST into account

I've read many SO articles, but I don't seem to be able to find a good answer to the problem. Posted suggestions include functions that convert dates to and from strings more then once, concatenating bits on the end and it all just seems... messy
So to the problem:
We have servers around the world. All servers run in their own local time and keep logs with time entries that are local to the server. Some servers are in DST observing areas, others arent
Suppose I have these strings from a log: 2013-01-01 12:34:56, 2013-07-01 12:34:56
And I know that this server is in New York so it's UTC-5 or UTC-4 when DST is in operation
And I have the same strings from a log on a server in Hong Kong, where DST does not apply and the time zone is +8
What I'm after is a block of code where I can tell it:
Here is a string representing a time
Here is the timezone the string is from
Daylight Savings should apply if relevant
And the code will parse the string into a DateTimeOffset, where the offset is adjusted according to DST if the time being parsed is DST relevant
For example:
NY server log says "2013-01-01 ..." DST does NOT apply to this date in JANUARY so the date parsed should be:
12:34:56 in new york time, a.k.a 17:34:56 in UTC (because it's -5, no DST)
NY server log says "2013-07-01 ..." DST DOES apply to this date in june so the date parsed should be:
12:34:56 in new york time, a.k.a 16:34:56 in UTC (because it's -4, with the DST)
HK server, both date times parse to 04:34:56 UTC
Thanks guys
Firstly, I'd strongly recommend that you change the system to log in UTC everywhere. It'll make your life much simpler.
If you're really stuck with what you've got, you should use DateTime.TryParseExact with a DateTimeStyles of just 0 (the default). That will give you a value with a DateTimeKind of Unspecified, which is what you want. (It's not UTC, and it's not local to the machine doing the parsing.)
You can then use TimeZoneInfo.GetUtcOffset (with the right time zone for that log) to work out the offset, and create a DateTimeOffset from the two together.
As a completely biased aside, you could also change to use the Noda Time project I maintain, which will allow your code to be much simpler to understand :)
To get the UTC-times of the time logged in the different log files you will need to know the names of the local time zones. Then you can use the DateTimeOffset-struct TimeZoneInfo-class to calculate the UTC-times:
public DateTime ParseAsUtc(string logDate, string timezoneName)
{
var timeZone = TimeZoneInfo.FindSystemTimeZoneById(timezoneName);
var localDate = DateTime.Parse(logDate);
var offset = new DateTimeOffset(localDate, timeZone.GetUtcOffset(localDate));
return offset.ToUniversalTime().DateTime;
}
ParseAsUtc("2013-01-01 12:34:56", "Eastern Standard Time"); //01.01.2013 17:34:56
ParseAsUtc("2013-07-01 12:34:56", "Eastern Standard Time"); //01.07.2013 16:34:56
ParseAsUtc("2013-01-01 12:34:56", "China Standard Time"); //01.01.2013 04:34:56
ParseAsUtc("2013-01-01 12:34:56", "China Standard Time"); //01.07.2013 04:34:56

Apply DateTime offset to US Eastern Timezone

I have a page that generates vCal and iCal files to import events into Outlook and iCal. These mail clients (Outlook & iCal) will take in the dates in UTC since they know the user's offset and will handle putting in the right times. Our client for which we're writing this code is based out of the USA Eastern time zone and so am I. Their host is in the Central time zone (1 hour behind Eastern). I'd like to make the code handle this without any hard-coded offsets. My code currently get's the DateTime from our CMS and converts to UTC for Outlook/iCal. That means the DateTime value from the CMS is relative to the hosting location:
// Start Date Time
sb.AppendFormat("DTSTART:{0}\n", thisEvent.StartDate.ToUniversalTime().ToString("yyyyMMddTHHmmssZ"));
When I run this on my local, it's all fine, because the DateTime in the CMS is based on our client's Eastern time zone and so am I, so the process is Eastern -> UTC -> into Outlook which then goes UTC -> Eastern, and everything is good. When I deploy to the server in Central, the DateTime from the CMS is an hour off from Eastern. How can I automatically get the offset from Eastern and add it in before I convert to UTC? I obviously need this to handle both standard time (EST) and daylight time (EDT). I'd like to do it programatically without hard-coded values so it always works correctly no matter what time zone you're in. I.e. if I deliver this code to someone for development in India, it should automatically handle their local server's offset and adjust accordingly.
I need to do something like this where I apply an offset to Eastern time before converting to UTC:
sb.AppendFormat("DTSTART:{0}\n", thisEvent.StartDate.ApplyEasternOffset().ToUniversalTime().ToString("yyyyMMddTHHmmssZ"));
Sorry if this is a topic that's been discussed before, I'm just not sure of the best terms to find a question like this. Thanks in advance.
Check out the TimeZoneInfo class. It has methods to get UTC offsets for any timezone.
http://msdn.microsoft.com/en-us/library/system.timezoneinfo.aspx
Also, check out this previous post: How to use TimeZoneInfo to get local time during Daylight Savings Time?
Here's an example showing a conversion from Pacfic to Eastern:
var eastern = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
var local = TimeZoneInfo.Local; // PDT for me
Console.WriteLine(DateTime.Now.Add(eastern.BaseUtcOffset - local.BaseUtcOffset));
Shows 4/4/2011 12:05:31 when my local clock shows 9:05:31.
You can use TimeZoneInfo Class.
Take a look at this sample:
TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById("US Eastern Standard Time");
TimeSpan offset = tzi.GetUtcOffset(DateTime.Now);
DateTime testDateTime = DateTime.Now.Add(offset);

Storing date/times as UTC in database

I am storing date/times in the database as UTC and computing them inside my application back to local time based on the specific timezone. Say for example I have the following date/time:
01/04/2010 00:00
Say it is for a country e.g. UK which observes DST (Daylight Savings Time) and at this particular time we are in daylight savings. When I convert this date to UTC and store it in the database it is actually stored as:
31/03/2010 23:00
As the date would be adjusted -1 hours for DST. This works fine when your observing DST at time of submission. However, what happens when the clock is adjusted back? When I pull that date from the database and convert it to local time that particular datetime would be seen as 31/03/2010 23:00 when in reality it was processed as 01/04/2010 00:00.
Correct me if I am wrong but isn't this a bit of a flaw when storing times as UTC?
Example of Timezone conversion
Basically what I am doing is storing the date/times of when information is being submitted to my system in order to allow users to do a range report. Here is how I am storing the date/times:
public DateTime LocalDateTime(string timeZoneId)
{
var tzi = TimeZoneInfo.FindSystemTimeZoneById(timeZoneId);
return TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, tzi).ToUniversalTime().ToLocalTime();
}
Storing as UTC:
var localDateTime = LocalDateTime("AUS Eastern Standard Time");
WriteToDB(localDateTime.ToUniversalTime());
You don't adjust the date for DST changes based on whether you're currently observing them - you adjust it based on whether DST is observed at the instant you're describing. So in the case of January, you wouldn't apply the adjustment.
There is a problem, however - some local times are ambiguous. For example, 1:30am on October 31st 2010 in the UK can either represent UTC 01:30 or UTC 02:30, because the clocks go back from 2am to 1am. You can get from any instant represented in UTC to the local time which would be displayed at that instant, but the operation isn't reversible.
Likewise it's very possible for you to have a local time which never occurs - 1:30am on March 28th 2010 didn't happen in the UK, for example - because at 1am the clocks jumped forward to 2am.
The long and the short of it is that if you're trying to represent an instant in time, you can use UTC and get an unambiguous representation. If you're trying to represent a time in a particular time zone, you'll need the time zone itself (e.g. Europe/London) and either the UTC representation of the instant or the local date and time with the offset at that particular time (to disambiguate around DST transitions). Another alternative is to only store UTC and the offset from it; that allows you to tell the local time at that instant, but it means you can't predict what the local time would be a minute later, as you don't really know the time zone. (This is what DateTimeOffset stores, basically.)
We're hoping to make this reasonably easy to handle in Noda Time, but you'll still need to be aware of it as a possibility.
EDIT:
The code you've shown is incorrect. Here's why. I've changed the structure of the code to make it easier to see, but you'll see it's performing the same calls.
var tzi = TimeZoneInfo.FindSystemTimeZoneById("AUS Eastern Standard Time");
var aussieTime = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, tzi);
var serverLocalTime = aussieTime.ToLocalTime();
var utcTime = serverLocalTime.ToUniversalTime();
So, let's think about right now - which is 13:38 in my local time (UTC+1, in London), 12:38 UTC, 22:39 in Sydney.
Your code will give:
aussieTime = 22:39 (correct)
serverLocalTime = 23:39 (*not* correct)
utcTime = 22:39 (*not* correct)
You should not call ToLocalTime on the result of TimeZoneInfo.ConvertTimeFromUtc - it will assume that it's being called on a UTC DateTime (unless it's actually got a kind of DateTimeKind.Local, which it won't in this case).
So if you're accurately saving 22:39 in this case, you aren't accurately saving the current time in UTC.
It's good that you are attempting to store the dates and times as UTC. It is generally best and easiest to think of UTC as the actual date and time and local times are just pseudonyms for that. And UTC is absolutely critical if you need to do any math on the date/time values to get timespans. I generally manipulate dates internally as UTC, and only convert to local time when displaying the value to the user (if it's necessary).
The bug that you are experiencing is that you are incorrectly assigning the local time zone to the date/time values. In January in the UK it is incorrect to interpret a local time as being in a Summertime time zone. You should use the time zone that was in effect at the time and location that the time value represents.
Translating the time back for display depends entirely on the requirements of the system. You could either display the times as the user's local time or as the source time for the data. But either way, Daylight Saving/Summertime adjustments should be applied appropriately for the target time zone and time.
You could work around this by also storing the particular offset used when converting to UTC. In your example, you'd store the date as something like
31/12/2009 23:00 +0100
When displaying this to the user, you can use that same offset to convert, or their current local offset, as you choose.
This approach also comes with its own problems. Time is a messy thing.
The TimeZoneInfo.ConvertTimeFromUtc() method will solve your problem:
using System;
class Program {
static void Main(string[] args) {
DateTime dt1 = new DateTime(2009, 12, 31, 23, 0, 0, DateTimeKind.Utc);
TimeZoneInfo tz = TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time");
Console.WriteLine(TimeZoneInfo.ConvertTimeFromUtc(dt1, tz));
DateTime dt2 = new DateTime(2010, 4, 1, 23, 0, 0, DateTimeKind.Utc);
Console.WriteLine(TimeZoneInfo.ConvertTimeFromUtc(dt2, tz));
Console.ReadLine();
}
}
Output:
12/31/2009 11:00:00 PM
4/2/2010 12:00:00 AM
You'll need .NET 3.5 or better and run on an operating system that keeps historical daylight saving time changes (Vista, Win7 or Win2008).
Correct me if I am wrong but isn't
this a bit of a flaw when storing
times as UTC?
Yes it is. Also, days of the adjustment will have either 23 or 25 hours so the idiom of the prior day at the same time being local time - 24 hours is wrong 2 days a year.
The fix is picking one standard and sticking with it. Storing dates as UTC and displaying as local is pretty standard. Just don't use a shortcut of doing calculations local (+- somthing) = new time and you are OK.
This is a huge flaw but it isn't a flaw of storing times in UTC (because that is the only reasonable thing to do -- storing local times is always a disaster). This is a flaw is the concept of daylight savings time.
The real problem is that the time zone information changes. The DST rules are dynamic and historic. They time when DST starting in USA in 2010 is not the same when it started in 2000. Until recently Windows did not even contain this historic data, so it was essentially impossible to do things correctly. You had to use the tz database to get it right. Now I just googled it and it appears that .NET 3.5 and Vista (I assume Windows 2008 too) has done some improvement and the System.TimeZoneInfo actually handles historic data. Take a look at this.
But basically DST must go.

How to convert time between timezones (UTC to EDT)?

I need to have a common function to convert UTC time to EDT. I have a server in India. An application in it needs to use EDT time for all time purposes.
I am using .NET 3.5.
I found this on some other forum.
DateTime eastern = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(
DateTime.UtcNow, "Eastern Standard Time");
When i tried with "Easten Daylight Time" I got an error.
"The time zone ID 'Eastern Daylight Time' was not found on the local computer".
Please help with this or any other solution.
Eastern Daylight Time isn't the name of a "full" time zone - it's "half" a time zone, effectively, always 4 hours behind UTC. (There may be proper terminology for this, but I'm not aware of it.)
Why would you want to use EDT for times which don't have daylight savings applied? If you want a custom time zone that always has the same offset to UTC, use TimeZoneInfo.CreateCustomTimeZone.
Note that if you use get the Eastern Standard timezone (TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time")) then that will still have daylight saving time applied appropriately (i.e. during summer).
For example:
TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
// Prints True
Console.WriteLine(tzi.IsDaylightSavingTime(new DateTime(2009, 6, 1)));
// Prints False
Console.WriteLine(tzi.IsDaylightSavingTime(new DateTime(2009, 1, 1)));
I would have said that you should use UTC for calculations of time periods, so that you avoid issues of daylight saving time and then use LocalTime for display only.
DateTime.ToLocalTime for UTC to whatever the local time zone is and then DateTime.ToUniversalTime to convert from local time to UTC.
Edit after comment 1
Do I take it then that you're after displaying a different timezone to that of the server?
If you're using web pages to access your server then use
HttpRequest.UserLanguages to help create a CultureInfo object and use that to parse your DateTime object.
Look here for a full explanation:Microsoft link on displaying local user time for web pages.
If you're using client-server architecture then if the LocalTime call is on the client side it will display the LocalTime for the client. You then convert it to UTC to send back to your server.
Either way your server doesn't need to know where the client is so if you have multiple clients in multiple timezones then all calculations will match. It will also allow you to show the times in any timezone that you wish by use of different Culture objects.
Edit 2 copied my second comment
You can get time data in UTC format from the server. Then you can convert it using DateTime.ToLocalTime or DateTime.ToUniversalTime as requried. If you're including dates as well and need to cope with say US MM/dd/yyyy and european dd/MM/yyyy formats the you can use CultureInfo class to parse the DateTime value accordingly. It sounds like more work than what you have at the moment, but it would mean that if you move your server again then you don't need to recode the DateTime handling.
A new point
Another point to look at is clock synchronisation between the server and the clients using NTP (Network Time Protocol) or SNTP (Simple Network Time Protocol) if it is accurate enough. I don't know what OS you are using but this is used by Windows Server time services to synchronise networks.
The cowboy method is to take the UTC time, subtract four hours' worth of seconds from it (the timezone offset), format it using a UTC formatting function, and slap a "EDT" label on it.
If you need to use Daylight Time sometimes and Standard Time other times, either make a lookup table of switchover dates, or use some calendar function.
TimeZoneInfo.ConvertTimeFromUtc will have correct offset depending on the DateTime you give it. For example:
3AM UTC/11PM ET (4 hour offset):
DateTime timeSummerET = TimeZoneInfo.ConvertTimeFromUtc(Convert.ToDateTime("08/01/2019 03:00:00"), zoneET);
3AM UTC/10PM ET (5 hour offset):
DateTime timeWinterET = TimeZoneInfo.ConvertTimeFromUtc(Convert.ToDateTime("12/01/2019 03:00:00"), zoneET);

Categories