We are dealing with an application that needs to handle global time data from different time zones and daylight savings time settings. The idea is to store everything in UTC format internally and only convert back and forth for the localized user interfaces. Does the SQL Server offer any mechanisms for dealing with the translations given a time, a country and a timezone?
This must be a common problem, so I'm surprised google wouldn't turn up anything usable.
Any pointers?
This works for dates that currently have the same UTC offset as SQL Server's host; it doesn't account for daylight savings changes. Replace YOUR_DATE with the local date to convert.
SELECT DATEADD(second, DATEDIFF(second, GETDATE(), GETUTCDATE()), YOUR_DATE);
7 years passed and...
actually there's this new SQL Server 2016 feature that does exactly what you need.
It is called AT TIME ZONE and it converts date to a specified time zone considering DST (daylight saving time) changes.
More info here:
https://msdn.microsoft.com/en-us/library/mt612795.aspx
While a few of these answers will get you in the ballpark, you cannot do what you're trying to do with arbitrary dates for SqlServer 2005 and earlier because of daylight savings time. Using the difference between the current local and current UTC will give me the offset as it exists today. I have not found a way to determine what the offset would have been for the date in question.
That said, I know that SqlServer 2008 provides some new date functions that may address that issue, but folks using an earlier version need to be aware of the limitations.
Our approach is to persist UTC and perform the conversion on the client side where we have more control over the conversion's accuracy.
Here is the code to convert one zone DateTime to another zone DateTime
DECLARE #UTCDateTime DATETIME = GETUTCDATE();
DECLARE #ConvertedZoneDateTime DATETIME;
-- 'UTC' to 'India Standard Time' DATETIME
SET #ConvertedZoneDateTime = #UTCDateTime AT TIME ZONE 'UTC' AT TIME ZONE 'India Standard Time'
SELECT #UTCDateTime AS UTCDATE,#ConvertedZoneDateTime AS IndiaStandardTime
-- 'India Standard Time' to 'UTC' DATETIME
SET #UTCDateTime = #ConvertedZoneDateTime AT TIME ZONE 'India Standard Time' AT TIME ZONE 'UTC'
SELECT #ConvertedZoneDateTime AS IndiaStandardTime,#UTCDateTime AS UTCDATE
Note: AT TIME ZONE works only on SQL Server 2016+ and the advantage is that it automatically considers Daylight when converting to a particular Time zone
For SQL Server 2016 and newer, and Azure SQL Database, use the built in AT TIME ZONE statement.
For older editions of SQL Server, you can use my SQL Server Time Zone Support project to convert between IANA standard time zones, as listed here.
UTC to Local is like this:
SELECT Tzdb.UtcToLocal('2015-07-01 00:00:00', 'America/Los_Angeles')
Local to UTC is like this:
SELECT Tzdb.LocalToUtc('2015-07-01 00:00:00', 'America/Los_Angeles', 1, 1)
The numeric options are flag for controlling the behavior when the local time values are affected by daylight saving time. These are described in detail in the project's documentation.
SQL Server 2008 has a type called datetimeoffset. It's really useful for this type of stuff.
http://msdn.microsoft.com/en-us/library/bb630289.aspx
Then you can use the function SWITCHOFFSET to move it from one timezone to another, but still keeping the same UTC value.
http://msdn.microsoft.com/en-us/library/bb677244.aspx
Rob
I tend to lean towards using DateTimeOffset for all date-time storage that isn't related to a local event (ie: meeting/party, etc, 12pm-3pm at the museum).
To get the current DTO as UTC:
DECLARE #utcNow DATETIMEOFFSET = CONVERT(DATETIMEOFFSET, SYSUTCDATETIME())
DECLARE #utcToday DATE = CONVERT(DATE, #utcNow);
DECLARE #utcTomorrow DATE = DATEADD(D, 1, #utcNow);
SELECT #utcToday [today]
,#utcTomorrow [tomorrow]
,#utcNow [utcNow]
NOTE: I will always use UTC when sending over the wire... client-side JS can easily get to/from local UTC. See: new Date().toJSON() ...
The following JS will handle parsing a UTC/GMT date in ISO8601 format to a local datetime.
if (typeof Date.fromISOString != 'function') {
//method to handle conversion from an ISO-8601 style string to a Date object
// Date.fromISOString("2009-07-03T16:09:45Z")
// Fri Jul 03 2009 09:09:45 GMT-0700
Date.fromISOString = function(input) {
var date = new Date(input); //EcmaScript5 includes ISO-8601 style parsing
if (!isNaN(date)) return date;
//early shorting of invalid input
if (typeof input !== "string" || input.length < 10 || input.length > 40) return null;
var iso8601Format = /^(\d{4})-(\d{2})-(\d{2})((([T ](\d{2}):(\d{2})(:(\d{2})(\.(\d{1,12}))?)?)?)?)?([Zz]|([-+])(\d{2})\:?(\d{2}))?$/;
//normalize input
var input = input.toString().replace(/^\s+/,'').replace(/\s+$/,'');
if (!iso8601Format.test(input))
return null; //invalid format
var d = input.match(iso8601Format);
var offset = 0;
date = new Date(+d[1], +d[2]-1, +d[3], +d[7] || 0, +d[8] || 0, +d[10] || 0, Math.round(+("0." + (d[12] || 0)) * 1000));
//use specified offset
if (d[13] == 'Z') offset = 0-date.getTimezoneOffset();
else if (d[13]) offset = ((parseInt(d[15],10) * 60) + (parseInt(d[16],10)) * ((d[14] == '-') ? 1 : -1)) - date.getTimezoneOffset();
date.setTime(date.getTime() + (offset * 60000));
if (date.getTime() <= new Date(-62135571600000).getTime()) // CLR DateTime.MinValue
return null;
return date;
};
}
Yes, to some degree as detailed here.
The approach I've used (pre-2008) is to do the conversion in the .NET business logic before inserting into the DB.
You can use GETUTCDATE() function to get UTC datetime
Probably you can select difference between GETUTCDATE() and GETDATE() and use this difference to ajust your dates to UTC
But I agree with previous message, that it is much easier to control right datetime in the business layer (in .NET, for example).
SUBSTRING(CONVERT(VARCHAR(34), SYSDATETIMEOFFSET()), 29, 5)
Returns (for example):
-06:0
Not 100% positive this will always work.
Sample usage:
SELECT
Getdate=GETDATE()
,SysDateTimeOffset=SYSDATETIMEOFFSET()
,SWITCHOFFSET=SWITCHOFFSET(SYSDATETIMEOFFSET(),0)
,GetutcDate=GETUTCDATE()
GO
Returns:
Getdate SysDateTimeOffset SWITCHOFFSET GetutcDate
2013-12-06 15:54:55.373 2013-12-06 15:54:55.3765498 -08:00 2013-12-06 23:54:55.3765498 +00:00 2013-12-06 23:54:55.373
Related
I have database table that has datetime field in SQL Server.
I have to send as below sample.
Can you please help how to get this dateformat?
Example: 2020-06-10T13:11:00-05:00
Thanks
If you were on a supported version of SQL Server, this is actually quite trivial. If we assume the value in the table is 2020-06-10T13:11:00 it would just need a CONVERT and SWITCHOFFSET:
SELECT V.Dt,
SWITCHOFFSET(CONVERT(datetimeoffset(0),V.dt),'-05:00')
FROM (VALUES(CONVERT(datetime2(0),'2020-06-10T13:11:00')))V(Dt);
If it's actually a UTC time, and you need to change it to (I assume) Central, then it would be:
SELECT V.Dt,
CONVERT(datetimeoffset(0),V.dt) AT TIME ZONE 'Central Standard Time'
FROM (VALUES(CONVERT(datetime2(0),'2020-06-10T18:11:00')))V(Dt);
Instead, you're going to have to do some varchar manipulation, as you're using a version of SQL Server that is completely unsupported:
--If switching the offset
SELECT V.Dt,
CONVERT(datetimeoffset(0),CONVERT(varchar(20),V.Dt,126) + '-05:00')
FROM (VALUES(CONVERT(datetime2(0),'2020-06-10T13:11:00')))V(Dt);
--If changing the offset
SELECT V.Dt,
CONVERT(datetimeoffset(0),CONVERT(varchar(20),DATEADD(HOUR, -5,V.Dt),126) + '-05:00')
FROM (VALUES(CONVERT(datetime2(0),'2020-06-10T18:11:00')))V(Dt);
Note that both of these are DST agnositic, as it SWITCHOFFSET. Only AT TIME ZONE will consider the DST.
I want to convert Eastern time ("GMT-05:00") into IST ("GMT+05:30") in SQL Server 2008.
It should based on Bias & DayLightBias.
Ex: Eastern Time has Bias value 300 & DaylightBias value -60 & IST has Bias value -330 & DayLightBias value -60.
I know how to convert this in C# but I want to create a job and for that I need this conversion in SQL Server.
Use the DATETIMEOFFSET datatype and the SWITCHOFFSET method in SQL Server 2008 or newer:
-- define your input in Eastern Time
DECLARE #Input DATETIMEOFFSET = SYSDATETIME()
-- SET #Input = SWITCHOFFSET(#Input, '-05:00')
SET #Input = SWITCHOFFSET(#Input, -300)
DECLARE #output DATETIMEOFFSET
-- convert Eastern Time to IST
-- SET #output = SWITCHOFFSET(#input, '+05:30')
SET #output = SWITCHOFFSET(#input, 330)
SELECT #Input, #output
MSDN SQL Server Books Online documentation for DATETIMEOFFSET
MSDN SQL Server Books Online documentation for SWITCHOFFSET
There are a lot more things to consider other than just the base offset and dst bias. Specifically, different offsets switch between standard and daylight time on different dates and at different times.
The correct way is with a named time zone. Unlike many other databases, SQL Server does not have native support for time zones. It only has support for time zone offsets. See "Time Zone != Offset" in the timezone tag wiki.
Fortunately, I've done all the hard work for you. Using my SQL Server Time Zone Support project, you can write this query:
SELECT Tzdb.ConvertZone(yourDateTimeValue, 'America/New_York', 'Asia/Kolkata', 1, 1)
The time zones are standard IANA tz database identifiers, and the numerical options at the end are explained in the project's readme.
According to the documentation I've found from AR Systems on BMC Remedy, timestamps in an MSSQL Server environment (we're using SQL Server 2005 here) are stored as an int datatype in UNIX timestamp format.
I cannot for the life of me get custom SQL in Business Objects Web Intelligence to let me convert this timestamp into mm/dd/yyyy format, which I need to be able to group records by a date (without the timestamp, obviously). Anything I try to do involving math or datatype conversion throws an "invalid type" error. I can't convert the field to an int, varchar, datetime, or anything else. The only function that works is DATEADD, which still returns the full timestamp.
How can I get this converted? I'm going nuts here!
to convert GMT/UTC/Zulu to Local time Zone(EDT/New York):
DATEADD(hour,-5,DATEADD(s,Last_Modified_Date,'1/1/1970 00:00:00'))
Example of use to display Remedy work info entries (Transact-SQL):
SELECT Work_Log_ID, DATEADD(hour, +12, DATEADD(s, Last_Modified_Date, '1/1/1970 00:00:00')) as Last_Modified_Date , Description, Detailed_Description, Infrastructure_change_ID, Number_of_Attachments
FROM dbo.CHG_WorkLog
WHERE Infrastructure_Change_ID = 'CRQ001261'
ORDER BY Work_Log_ID desc
Why doesn't this work?
DECLARE #timestamp INT
SELECT #timestamp = DATEDIFF(s,'1/1/1970 00:00:00',GETDATE())
SELECT DATEADD(s,#timestamp,'1/1/1970 00:00:00')
Substitute the #Timestamp with the value from your table.
You may need to multiply the int timestamp by 1000. The AR System stores the date as the number of 'seconds' where as most other languages store the unix timestamp as milliseconds (and as a long data type)
Hope that helps!
Go to
user tool -> Tools -> Options -> Locale tab -> Date/Time Style -> Custom Format -> mm/dd/yyyy
I would like to know which format SQL Server saves datetimes, GMT or UMT?
The default DATETIME value in SQL Server has no knowledge of time zones and thus doesn't really care about time zones - that's entirely up to you to manage.
DECLARE #MyDate DATETIME
SET #MyDate = '20100922 04:05:06' --- no information on timezone
See MSDN docs on DATETIME.
With SQL Server 2008, a new data type was introduced called DATETIMEOFFSET which stores time along with a timezone offset. So here, you can store the local time and store the timezone that time is local to as well.
DECLARE #MyDateOffset DATETIMEOFFSET
SET #MyDateOffset = '20100922 04:05:06 +09:00' -- UTC plus 9 hours
Neither, it just returns the values in a specific format but stores it in a format without a timezone.
All my times are in UTC timezone now I need to somehow convert it to the users timezone(I have it stored in the db as well and uses the ids of the windows timezones).
How can I do this in SQL Server 2005?
Edit
So I tried to do that extended stored procedure but with Timezoneinfo I get this error
Deploy error SQL01268: .Net SqlClient
Data Provider: Msg 6503, Level 16,
State 12, Line 1 Assembly
'system.core, version=3.5.0.0,
culture=neutral,
publickeytoken=b77a5c561934e089.' was
not found in the SQL catalog. An
error occurred while the batch was
being executed.
if I take that line out I can deploy it. Any ideas how to get around this?
Since SQL Server doesn't provide out of the box support for this, you might consider writing a .Net dll stored procedure, that makes use of the .Net TimeZoneInfo object , this object takes all rules including DST into consideration. This class allows you to convert time from one zone to another too. I hope this helps.
DateTime hwTime = new DateTime(2007, 02, 01, 08, 00, 00);
try
{
TimeZoneInfo hwZone = TimeZoneInfo.FindSystemTimeZoneById("Hawaiian Standard Time");
Console.WriteLine("{0} {1} is {2} local time.",
hwTime,
hwZone.IsDaylightSavingTime(hwTime) ? hwZone.DaylightName : hwZone.StandardName,
TimeZoneInfo.ConvertTime(hwTime, hwZone, TimeZoneInfo.Local));
}
catch (TimeZoneNotFoundException)
{
Console.WriteLine("The registry does not define the Hawaiian Standard Time zone.");
}
catch (InvalidTimeZoneException)
{
Console.WriteLine("Registry data on the Hawaiian STandard Time zone has been corrupted.");
}
[Edit]
Tutorial Creating Simple .Net DLL stored procedure.
Another useful tutorial, has more detail on deployment.
SQL Server does not provide a simple
way to convert a UTC datetime value to
a local time value.
However, the page that is from includes:
A table (tbTimeZoneInfo) with
data to provide the Time Zone
information and two functions to
convert a UTC datetime value to any
Local Time Zone.
Wrote this just for you:
DECLARE #UTCDate DateTime /* Replace with the UTC datetime stored in your table */
DECLARE #LocalDate DateTime
DECLARE #TimeZoneOffset int /* Replace with the offset stored in your table */
SET #TimeZoneOffset = -8 /* PST */
SET #UTCDate = GETUTCDATE()
SET #LocalDate = DATEADD(Hour, #TimeZoneOffset, #UTCDate)
SELECT #UTCDate
SELECT #LocalDate
Let me know if it doesn't work.
SQL Server 2008 would have the DATETIMEOFFSET data type (which includes the time zone) plus functions like SWITCHOFFSET to switch from one timezone offset to another.
But on the 2005 version, there's not much support for timezones.
Any chance you could upgrade any time soon??
I use this function:
CREATE FUNCTION fnConvertGMTToLocalTime
(
#GMTValue Datetime,
#TimeZoneOffset int
)
RETURNS DateTime
AS
BEGIN
DECLARE #LocalTime dateTime
SELECT #LocalTime = DateAdd(Hour, #TimeZoneOffset, #GMTvalue)
RETURN #LocalTime
END
It doesn't consider daylight savings time...but i don't need that anyway.