In C#, convert Sql Server 2005 datetime value to another timezone - c#

UPDATE
I am dealing with a legacy database where the datetime values have been stored in a specific timezone (not UTC). Assume it is not possible to change how we are storing these values.
END UPDATE
Say I have a SQL Server 2005 database with a table as follows:
[id] (int) not null
[create_date] (datetime) not null
Suppose my [create_date] has been stored, by convention, as timezone TZ-A.
Suppose I want to retrieve this value (using SqlClient) from the database and display it in another timezone, TZ-B.
How do I do this?
DateTime from_db = // retrieve datetime from database, in timezone TZ-A
DateTime to_display = //convert from_db to another timezone, TZ-B

Use TimeZoneInfo
TimeZoneInfo timeZone1 = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time");
TimeZoneInfo timeZone2 = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
DateTime to_display= TimeZoneInfo.ConvertTime(from_db, timeZone1, timeZone2);
I also agree that storing in UTC is the way to go. The only downside is trying to explain UTC to users who want to write their own reports.

Everyone has C# ways, I give you TSQL (sadly only 2008):
See below for doc, you probably want something like:
-- up here set the #time_zone variable.
SELECT
COl0, TODATETIMEOFFSET(COLDATE, #time_zone),.... ColN, from
Table_Original;
From MSDN
The SWITCHOFFSET function adjusts an
input DATETIMEOFFSET value to a
specified time zone, while preserving
the UTC value. The syntax is
SWITCHOFFSET(datetimeoffset_value,
time_zone). For example, the following
code adjusts the current system
datetimeoffset value to time zone GMT
+05:00:
SELECT
SWITCHOFFSET(SYSDATETIMEOFFSET(),
'-05:00');
So if the current system
datetimeoffset value is February 12,
2009 10:00:00.0000000 -08:00, this
code returns the value February 12,
2009 13:00:00.0000000 -05:00.
The TODATETIMEOFFSET function sets the
time zone offset of an input date and
time value. Its syntax is
TODATETIMEOFFSET(date_and_time_value,
time_zone).
This function is different from
SWITCHOFFSET in several ways. First,
it is not restricted to a
datetimeoffset value as input; rather
it accepts any date and time data
type. Second, it does not try to
adjust the time based on the time zone
difference between the source value
and the specified time zone but
instead simply returns the input date
and time value with the specified time
zone as a datetimeoffset value.
The main purpose of the
TODATETIMEOFFSET function is to
convert types that are not time zone
aware to DATETIMEOFFSET by the given
time zone offset. If the given date
and time value is a DATETIMEOFFSET,
the TODATETIMEOFFSET function changes
the DATETIMEOFFSET value based on the
same original local date and time
value plus the new given time zone
offset.
For example, the current system
datetimeoffset value is February 12,
2009 10:00:00.0000000 -08:00, and you
run the following code:
SELECT
TODATETIMEOFFSET(SYSDATETIMEOFFSET(),
'-05:00');
The value February 12, 2009
10:00:00.0000000 -05:00 is returned.
Remember that the SWITCHOFFSET
function returned February 12, 2009
13:00:00.0000000 -05:00 because it
adjusted the time based on the time
zone differences between the input
(-08:00) and the specified time zone
(-05:00).
As mentioned earlier, you can use the
TODATETIMEOFFSET function with any
date and time data type as input. For
example, the following code takes the
current system date and time value and
returns it as a datetimeoffset value
with a time zone -00:05:
SELECT TODATETIMEOFFSET(SYSDATETIME(),
'-05:00');

I'm not going to offer an answer, but rather a word of advice: Always store absolute dates in UTC, no matter what.

use the TimeZoneInfo class, it gives you built in time zone conversion functions using the Windows API.
http://msdn.microsoft.com/en-us/library/system.timezoneinfo.aspx

Always store the data in the database as UTC. Then convert it in the client for display purposes from UTC to the local time using DateTime.ToLocalTime();

Check the method TimeZoneInfo.ConvertTime.

Related

C# DateTimeOffset comparision with LocalDate

I'm consuming a Microsoft API which returns DateTimeOffset. The property has following documentation- This value is calculated based on current UTC time measured locally.
I want to compare this time with local server where my application is hosted. (So the DateTimeOffset is returned by Microsoft API and the place where I want to compare is on my server. These 2 can have different time zones).
When inspecting DateTimeOffset, Date & UTC property has same Date & Time and the Kind property is unspecified.
I'm currently using DateTimeOffset < DateTime.UtcNow for checking condition. Am I doing right?
You should use dateTimeOffset.LocalDateTime < dateTime.
.LocalDateTime method will convert the DateTimeOffset into your local time zone (with DateTimeKind.Local), so you can safely compare with your local DateTime.
You can get the offset time difference in the minutes using the below code
// Get the GMT time difference offset (This is your local time offset difference)
var timeOffsetinMiniut = DateTimeOffset.Now.Offset.TotalMinutes;
Now you can use add this offset in you local time to make it a UTC time.
var myNewDateTime = System.DateTime.Now.AddMinutes(timeOffsetinMiniut)
Now you can compare both time utc time and your new server time.
myNewDateTime < DateTime.UtcNow
Hope this will help you.
Thanks

How to combine date time and Timezone offset in an ASP.net application?

My web service call to a third party applications returns the date,time zone and timezone_offset values. I need to add this to a calendar in Asp.net application. What is the best way to combine this together so that my date object understands that its from Eastern time zone?
<start_date>2014-11-17 19:00:00</start_date>
<timezone>America/New_York</timezone>
<timezone_offset>GMT-0500</timezone_offset>
Since you have the offset too, you can use DateTimeOffset.Parse() to get the DateTimeOffset. From there, you can read the DateTime property. The output dt variable will have 2014-11-17 7:00:00 PM with DateTimeKind property set to "Unspecified"
var dtOffset = DateTimeOffset.Parse("2014-11-17 19:00:00-0500", CultureInfo.InvariantCulture);
var dt = dtOffset.DateTime;
A DateTimeOffset represents a point in time. Usually, its relative to UTC. So, it is a natural structure to initially parse the fields that you have.
If you want a reference to the same datetime in UTC, you can use this. Here the output dt variable will have 2014-11-18 12:00:00 AM with DateTimeKind property set to "Utc"
var dt = DateTime.Parse("2014-11-17 19:00:00-0500", CultureInfo.InvariantCulture).ToUniversalTime();
If you don't have the offset but just have the timeZoneId, you can still do it but you need NodaTime for that.
I'll focus on this part of the question:
What is the best way to combine this together so that my date object understands that its from Eastern time zone?
There is no data type built in to .NET that can sufficiently do that. The DateTimeOffset type associates with a particular offset, such as the -05:00 or -04:00 that might be in use by the Eastern time zone (depending on the date). But those same offsets might also be sourced from some other time zone entirely. A time zone has one or more offsets, but an offset isn't a time zone itself.
Fortunately there are solutions. There are two options to consider:
You could pair a DateTimeOffset with a TimeZoneInfo object. When storing or transmitting these, you would only send the full DateTimeOffset along with the Id of the time zone.
The Noda Time library is a much more effective way to work with date and time, especially when it comes to time zone concerns. It contains a type called ZonedDateTime that already combines a date, time, offset, and time zone. It can also be used to work with IANA time zone identifiers, such as the "America/New_York" time zone you specified in the question.

SharePoint DateTime default value respect timezone

I have a DateTime field (Date Only) that uses the "Today's Date" as a default value.
However, when a user adds an item to the list the date that is selected is respective to the GMT timezone.
Therfore if a user adds an item on 2/22/2012 at 7pm (EST) the default value will actually read 2/23/2012.
My first thought was to check the web application settings, and they were set to -5 EST. Then after some searching I found that time zones can differ based on a users regional settings. Testing this approach, I manually set a user to have a EST time zone, and performed the test that yielded the same result.
Finally, after more searching I found one article that said to use the Calculated Value portion of the DateTime field and specify "=NOW()"
This however returned "The formula contains a syntax error or is not supported."
Does anyone know of a way to have the default value of a DateTime field respect the time zone of the web application or the user?
Thank you.
Sharepoint stores all date field in UTC. That is, if you are saving a datetime field in a list, Sharepoint actually converts the time that you selected into UTC, and converts it back to whatever time zone the person is in when retrieving.
Begin by checking if there's a difference between your server timezone and your client. When using any API SharePoint will always return the UTC time and leave it up to you to make the conversion in your interface or application.
If you like to solve this differently you can't use the datetime datatype, instead store dates in text fields.
== UPDATE ==
If you got a date from SharePoint (always in UTC) and simply want to convert it to your local time this is a good practice
DateTime localDateTime = sharePointDate.ToLocalTime();
If you got the date as a string, or are uncertain of the formatting and whatnot this can be a good approach
string dateStr = ("2/18/2012 9:49:51 PM").ToString(CultureInfo.InvariantCulture);
DateTime convertedDate = DateTime.SpecifyKind(DateTime.Parse(dateStr), DateTimeKind.Utc);
DateTime localDateTime = convertedDate.ToLocalTime();
// Outputs 2/18/2012 10:49:51 PM since I'm +1 in sweden

Parse String DateTime containing TimeZone Info

I am trying to convert a string value to a datetime value but am getting a System.FormatException error. This is because of the timezone info which is part of the date string. Is there any method which will be able to handle this conversion?
string date = "Wed, 04 Jan 2012 20:18:00 EST";
DateTime dt = Convert.ToDateTime(date);
Console.WriteLine(dt.ToString());
I don't believe there's any custom date and time format string which will parse or format a time zone abbreviation. You'll have to strip it out, parse the local part, work out which time zone is meant from the abbreviation (good luck with that - they're ambiguous) and then apply that time zone to the local time to get a UTC value (again, this can be ambiguous).
If you're in control of the format at all, I would try to avoid including time zone information if you can, or include an offset rather than a time zone if that's all that's important (an offset doesn't give the same information of course), or an unambiguous time zone identifier if you really need the time zone. Note that .NET uses the Windows system time zone identifiers; my own Noda Time project uses the more widespread Olson / zoneinfo / tz identifiers, if that's helpful to you.

C#/.NET Date: From local to UTC

I get date data from a user. That data is a date (e.g. 4/23/2011) and an hour (0 - 23), representing the time. This date/time that the user selects is a local time.
I need to convert this to a UTC DateTime. I have their GMTOffset for their location. How can I do this?
You should work with the DateTimeOffset structure, specifically, the constructor that takes the DateTime and the TimeSpan that represents the offset.
From there, conversions to/from UTC are a breeze, as the offset is embedded in the structure and not dependent on local system settings.
Note, even though not commonly adhered to, it is recommended to work with DateTimeOffset most of the time, as opposed to DateTime (see the note under the section titled "The DateTimeOffset Structure").
var utcDateTime =
new DateTimeOffset(userDateTime, TimeSpan.FromHours(userUtcOffset)).UtcDateTime;
Of course you can use TimeSpan differently if the GMT offset has minutes / fractions of an hour.
Just use the DateTime.ToUniversalTime in C#, will that do what you want?

Categories

Resources