TimeZone Implementation For a SaaS [duplicate] - sql

I want to add my time zone with the function GETUTCDATE() in SQL Server. I searched several times, but did not found any relevant solution. Thanks in advance.

only for sql 2016, it takes into account daylight savings.
CREATE FUNCTION GetBelgiumTime
(
)
RETURNS datetime2
AS BEGIN
declare #dateoffset datetimeoffset
SET #dateoffset = convert(VARCHAR(2000),(SELECT GETUTCDATE() AT TIME ZONE 'Central European Standard Time'),126 )
declare #date datetime2
set #date = convert(datetime2, LEFT(#dateoffset,28),126)
set #date = DATEADD(HOUR, convert(int,LEFT(RIGHT(#dateoffset,5), 2)), #date)
RETURN #date
END
select dbo.GetBelgiumTime() as BelgiumDateAndTime

From SQL Server 2016 forward (and Azure SQL DB), you can do this:
SELECT SYSDATETIMEOFFSET() AT TIME ZONE #tz
where #tz is a valid Windows time zone identifier, such as 'Pacific Standard Time', 'Central European Standard Time', etc.
However, if you are on an older version of SQL Server, or prefer to use IANA time zone identifiers, you can use my SQL Server Time Zone Support project to do the following:
SELECT Tzdb.UtcToLocal(GETUTCDATE(), #tz)
where #tz is an IANA standard time zone name, such as 'America/Los_Angeles' or 'Europe/Budapest'.

Use GETDATE() instead GETUTCDATE(). see this link

You can try to use switchoffset like this:
select switchoffset(CAST(myDate as datetimeoffset),'+05:30') from someTable
Instead of '+05:30' you can specify your timezone value.
If you want to use the timezone with GETUTCDATE() then simply add it like this
select cast(GETUTCDATE() as varchar(20)) + '+5:30'
and if you want to keep it as date only then
select switchoffset(CAST(GETUTCDATE() as datetimeoffset),'+05:30')

Related

Azure SQL - Convert time zone to 'Central Standard Time'?

Server time is 'UTC' and cannot be changed due to my database being Azure SQL. I know you can convert to other time zones. However, I'm not sure how to apply this correctly.
In short. I need to be able to pull and job based on 'start date' but by Central Standard Time.
I did comment out where I tried some things. My issue is, I'm not sure how to apply the offset to the 'Start Date' for what is returned in the front end.
The 'WHERE' statement does technically work to only return 'Today's Jobs', however returns based on UTC time which won't work for people using this in Central Standard Time Zone. How do I offset this properly?
Much appreciation for the help.
begin
--declare #dto datetimeoffset = switchoffset (CONVERT(datetimeoffset, GETDATE()), '-6:00');
--DECLARE #dto datetimeoffset
--SET #dto = (SELECT GETUTCDATE() AT TIME ZONE 'Central Standard Time')
--SELECT SWITCHOFFSET(SYSDATETIMEOFFSET(), '-05:00')
declare #today datetimeoffset;
--set #today = switchoffset (convert(time, getdate()), '-05:00');
set #today = getdate();
SELECT dbo.Projects.ProjectID, dbo.Projects.ProjectName, dbo.Jobs.JobID, dbo.Jobs.Status, dbo.Jobs.StartDate, dbo.Jobs.EndDate, dbo.Jobs.CompletedDate, dbo.JobType.JobTypeID, dbo.JobType.JobTypeDescription
FROM dbo.Jobs INNER JOIN dbo.Projects ON dbo.Jobs.ProjectID = dbo.Projects.ProjectID
INNER JOIN dbo.JobType ON dbo.Jobs.JobTypeID = dbo.JobType.JobTypeID
WHERE convert(varchar(10), StartDate, 102)
= convert(varchar(10), #today, 102)
ORDER BY JobID DESC
End
Azure SQL database always follows UTC. Use AT TIME ZONE in Azure SQL Database if you need to convert date and time information in a non-UTC time zone.
AT TIME ZONE converts input date to target time zone. It returns datetimeoffset value in the target time zone.
Query:
declare #current_cst datetimeoffset;
set #current_cst = (SELECT getdate() AT TIME ZONE 'UTC' AT TIME ZONE 'Central Standard Time')
declare #current_utc datetimeoffset;
set #current_utc = getutcdate();
--retunrs datetimeoffset format
select #current_utc current_utc, #current_cst current_cst
--retunrs 102 format(yyyy.mm.dd)
select convert(varchar(10), #current_utc, 102) as current_utc, convert(varchar(10), #current_cst, 102) as current_cst
Note: A list of installed time zones are available in sys.time_zone_info view.

Proper way of getting rows since a date accounting for DST?

I have a datetime column, changedate, that I need to use to get rows that have changed in the last week since 1PM. This column is unfortunately in local time (EST). The server is Microsoft SQL Server 2016.
Here is the query I have now:
DECLARE #since datetime = DATEADD(week,-1,SMALLDATETIMEFROMPARTS(YEAR(GETDATE()), MONTH(GETDATE()), DAY(GETDATE()), 13, 0)) AT TIME ZONE 'Eastern Standard Time'
SELECT * FROM table WHERE changedate AT TIME ZONE 'Eastern Standard Time' >= #since
Since I'm using AT TIME ZONE for both the column and #since, will this properly account for DST changes? That's my understanding per the documentation I've found, but I'm not 100% sure if that's how it works or if I'm missing something.
First, figure out the time you're wanting to compare against:
-- Get the current date in the given time zone
DECLARE #today date = convert(date, sysdatetimeoffset() AT TIME ZONE 'Eastern Standard Time')
-- Get the date one week ago
DECLARE #dateOneWeekAgo date = DATEADD(week, -1, #today)
-- Join the date with the desired time (local to the same time zone)
DECLARE #since datetime = convert(datetime, #dateOneWeekAgo) + convert(datetime, timefromparts(1, 0, 0, 0, 0))
Then just compare it:
SELECT * FROM table WHERE changedate >= #since
That assumes your changedate field is a datetime or datetime2. If it's a datetimeoffset, you should first convert the target value to a datetimeoffset in the same time zone and use that instead:
DECLARE #sinceDTO datetimeoffset = #since AT TIME ZONE 'Eastern Standard Time'
Regarding the approach you gave in the question, there two issues:
getdate() gives the time based on the server's local time zone. It's possible that it's not the same day in Eastern Time.
You should never apply a function (whether an intrinsic like AT TIME ZONE or something else) against a table field in a where clause, because it makes the query non-sargable. In other words, SQL would have to scan the entire table, rather than using an index. The bigger the table, the slower the query would take.

DateDiff - DST issue

Background
I have a scenario where I am calculating the difference between two dates. While the increment differences are spot on, the final calculation has introduced a 60 minute (1 hour) disparity.
After investigation and "hair pulling" episodes, I have identified that the DST transition in November is the cause for the 60 minute (1 hr) disparity.
Scenario
declare #sdate datetime = '2016-10-29 06:03:00.000PM'
declare #edate datetime = '2016-11-29 11:59:00.000PM'
select
DATEDIFF(HOUR, #sdate, #edate),
DATEDIFF(Minute, #sdate, #edate),
DATEDIFF(Second, #sdate, #edate)
Question
Ultimately, I need to simply return the number of seconds, or minutes, between the #sdate and #edate variables. I know there will be two times during the year, where the difference value will be off by 60 minutes (1 hour), plus or minus, and want to account for that known disparity within my sql statement.
How can i account for the DST adjustment within a set-based operation, if possible?
Currently, I am getting 44996 as the difference, but that is the un-adjusted time-change difference. I am looking for 45056, which is the adjusted time-change difference.
The datetime type in SQL Server has no awareness of time zone or offset from UTC. In order to take DST into account, you need to use the datetimeoffset type.
declare #sdate datetimeoffset = '2016-10-29 06:03:00.000PM -05:00'
declare #edate datetimeoffset = '2016-11-29 11:59:00.000PM -06:00'
select
DATEDIFF(Hour, #sdate, #edate),
DATEDIFF(Minute, #sdate, #edate),
DATEDIFF(Second, #sdate, #edate)
This will give the results you asked for, taking into account that the offsets for the start and end differed by an hour.
The tricky part is how to determine the offset to begin with. If you are running SQL 2016, or Azure SQL DB, then you could use the AT TIME ZONE function to determine it.
declare #dt datetime = '2016-10-29 06:03:00.000PM'
declare #dto = #dt AT TIME ZONE 'Central Standard Time'
But since you said you are running SQL 2012, you'll have to either write your own functions that understand when DST starts and ends in your time zone, or you can use my SQL Server Time Zone Support package to do that:
declare #dt datetime = '2016-10-29 06:03:00.000PM'
declare #tz varchar = 'America/Chicago'
declare #dto = Tzdb.SwitchZone(Tzdb.LocalToUtc(#dt, #tz, 1, 1), #tz)
Note there is an open item to simplify this to a single function, but the above should work for now.

SQL Convert GETUTCDATE to nvarchar timezone like 'Eastern Standard Time'

I would like to convert a GETUTCDATE() call to a timezone using a timezone string like 'Eastern Standard Time' or any timezone string located in the registry under HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones. Is there a method to do that or am I venturing into SQLCLR territory?
Current suggestions I've seen:
print CONVERT(datetime2, DATEADD(HOUR, -4, GETUTCDATE()))
Output:
2015-09-08 15:22:50.5000000
I'd like to see this with DST working.
Is something like this possible?
print CONVERT(datetime2, DATEADD(HOUR, 'Eastern Standard Time', GETUTCDATE()))
I have SQL Server 2012 Standard available to me. Any suggestions? Thank you in advance!
You need to check out DATETIMEOFFSET datatype which is a datetime datatype that includes that timezone.
Also, there's a function called SWITCHOFFSET which allows you to switch a given DATETIMEOFFSET to another timezone.
With those two pieces, you can do:
DECLARE #CurrentDateTime DATETIMEOFFSET
SELECT #CurrentDateTime = SYSDATETIMEOFFSET()
DECLARE #OtherDateTime DATETIMEOFFSET
SELECT #OtherDateTime = SWITCHOFFSET(#CurrentDateTime, `-05:00')
You can use
SYSDATETIMEOFFSET() AT TIME ZONE 'Eastern Standard Time'
This returns datetime with offset in zone you specify. This can easly converted to datetime, datetime2

How can I convert a Sql Server 2008 DateTimeOffset to a DateTime

I'm hoping to convert a table which has a DATETIMEOFFSET field, down to a DATETIME field BUT recalculates the time by taking notice of the offset. This, in effect, converts the value to UTC.
eg.
CreatedOn: 2008-12-19 17:30:09.0000000 +11:00
that will get converted to
CreatedOn: 2008-12-19 06:30:09.0000000
or
CreatedOn: 2008-12-19 06:30:09.0000000 + 00:00 -- that's a `DATETIMEOFFSET`, but `UTC`.
Cheers :)
Converting using almost any style will cause the datetime2 value to be converted to UTC.
Also, conversion from datetime2 to datetimeoffset simply sets the offset at +00:00, per the below, so it is a quick way to convert from Datetimeoffset(offset!=0) to Datetimeoffset(+00:00)
declare #createdon datetimeoffset
set #createdon = '2008-12-19 17:30:09.1234567 +11:00'
select CONVERT(datetime2, #createdon, 1)
--Output: 2008-12-19 06:30:09.12
select convert(datetimeoffset,CONVERT(datetime2, #createdon, 1))
--Output: 2008-12-19 06:30:09.1234567 +00:00
I'd use the built in SQL option:
select SWITCHOFFSET(cast('2008-12-19 17:30:09.0000000 +11:00' as datetimeoffset),'+00:00')
I know this is an old question but, if you want to convert DateTimeOffset to a DateTime, I think you need to take into account the timezone of the server you are converting on. If you just do a CONVERT(datetime, #MyDate, 1) you will simply lose the time zone, which likely results in an incorrect conversion.
I think you first need to switch the offset of the DateTimeOffset value, then do the conversion.
DECLARE #MyDate DATETIMEOFFSET = '2013-11-21 00:00:00.0000000 -00:00';
SELECT CONVERT(DATETIME, SWITCHOFFSET(#MyDate, DATEPART(tz,SYSDATETIMEOFFSET())));
The result of converting '2013-11-21 00:00:00.0000000 -00:00' to a DateTime on a server who's offset is -7:00 will be 2013-11-20 17:00:00.000. With the above logic it doesn't mater what the time zone of the server or the offset of the DateTime value, it will be converted to DateTime in the servers time zone.
I believe you need to do this because a DateTime value includes an assumption that the value is in the time zone of the server.
DateTimeoffset (Timezone) conversion in SQL Server.
SQL Server 2016 (13.x) and later
Exmample
Select GETUTCDATE()
Select Convert(DATETIME, GETUTCDATE() AT TIME ZONE 'UTC' AT TIME ZONE 'Central European Standard Time')
Select Convert(DATETIME, GETUTCDATE() AT TIME ZONE 'UTC' AT TIME ZONE 'India Standard Time')
Result will be
2020-08-18 08:22:21.640
2020-08-18 10:22:21.640
2020-08-18 13:52:21.640
Note: The timezone information is discarded in conversion if no style ("126" here) is specified. It might also be discarded in some of the other styles, I don't know -- in any case the following correctly adjusts for the TZ information. See CAST and CONVERT.
select convert(datetime, cast('2008-12-19 17:30:09.0000000 +11:00' as datetimeoffset), 126) as utc;
Happy SQL'ing.
Edit
Not sure if it matters but ... datetime Can't actually store that level of precision/accuracy. If the above is run the fractional seconds will be truncated to 3 digits (and accuracy is less than that). The same-same with datetime2 (and datetimeoffset(7)) produces a non-truncated value:
select convert(datetime2, cast('2008-12-19 17:30:09.1234567 +11:00' as datetimeoffset(7)), 126) as utc;
In order to account for daylight savings time, I used the following:
CONVERT(
DateTime,
SWITCHOFFSET(
CONVERT(
DateTimeOffset,
CONVERT(
DateTime,
[time_stamp_end_of_interval],
120
)
),
DATENAME(
TzOffset,
CONVERT(
DateTime,
[time_stamp_end_of_interval],
120
) AT TIME ZONE 'Pacific Standard Time'
)
)
)
AS GOOD_PST
Note: time_stamp_end_of_interval is a varchar