Get a specific date in a specific time zone - sql

I am trying to derive a given date from a DB that is in Greenwich Mean Time. so I need to constantly account for the discrepancy.
DECLARE #date datetime
DECLARE #tempdate datetime = '3/1/2019'
SET #date = #tempdate AT TIME ZONE 'UTC' AT TIME ZONE 'Central Standard
Time'
SELECT #date
The above code produces a date several hours before March 1st (since I am in the U.S.). Is there a generic way to always grab Central Time for any desired date?

IF you are trying to convert UTC time into US Central Time it is indeed normal to receive a Central time that is earlier that UTC time. Sun rises in Greenwich first and sometime later rises in Chicago, so the March begins first in UTC zone, few hours prior to doing it in Chicago. Same goes for other months! :)

Related

Add offset value to time in SQL Server

I felt like this should be easy but I'm not finding answer. The query below will give me the current date/time in California and represent it as UTC with a timezone offset (currently -08:00):
select getdate() at time zone 'Pacific Standard Time'
I simply want to apply the offset and get a timestamp showing the current local time and then drop the offset. I feel like there should be a way to achieve this without having to pick through it with string and date functions. For example, I want to go from
2021-11-24 18:03:41.190 -08:00
to
2021-11-24 10:03:41.190
Is there a succinct way to do this?
When you use AT TIME ZONE on a value that isn't a datetimeoffset it's assumed that the value is at the time zone you are converting it to.
Instead, therefore, you could nest the AT TIME ZONE clauses. If you did do this though, I would also suggest using SYSUTCDATE rather than GETDATE (which returns the local time to the host, which could be any timezone).
SELECT SYSUTCDATETIME() AT TIME ZONE 'UTC' AT TIME ZONE 'Pacific Standard Time';
Though really, just use SYSDATETIMEOFFSET to start with; then you just need one AT TIME ZONE as the RDBMS already knows what timezone the value is for.
SELECT SYSDATETIMEOFFSET() AT TIME ZONE 'Pacific Standard Time';
db<>fiddle
Declare #myDateTime datetime = '2021-11-24 21:35:25.984'; --UTC time
Select cast(#myDateTime At Time Zone 'UTC' At Time Zone 'Pacific Standard Time' As datetime);
Or - you can just apply the desired offset and convert back to datetime
Select cast(switchoffset(#myDateTime, '-08:00') As datetime)
The problem with using switchoffset is that it isn't DST aware and would need to be changed to use a different offset value. If you change the date above to October - the PST time would be 14:35:25.983 but the second calculation still returns 13:35:25.983

SQL time in incorrect from that of my system timezone

We have a SQL database that returns all the times in Greenwich Mean Time (GMT). We are in the Eastern Standard Timezone (EST). This messes up some queries that we have that pull data from specific dates. I tried using the (StartTime AT TIME ZONE 'Eastern Standard Time' as StartTime_ET, but that only returns the result as same in GMT -5. I just want the exact result to be in EST .
This changes the complete logic process of mine. Is there any way to do that?
Assuming your values are all UTC and that your column StartTime is not a datetimeoffset, then you need to turn your value into a datetimeoffset first, and then change the time zone. When you use AT TIMEZONE on a date and time data type that isn't a DATETIMEOFFSET it is assumed that the value is already at the correct timezone. Therefore, for example something like SELECT GETUTCDATE() AT TIME ZONE 'Eastern Standard Time'; would return 2021-08-05 09:53:56.8500000 -04:00 right now, even though the time in EST is actually 2021-08-05 05:53:56.8500000 -04:00 right now.
As a result you need to add the offset first and then use AT TIME ZONE. So, with GETUTCDATE that would be like this:
SELECT SWITCHOFFSET(GETUTCDATE(),0) AT TIME ZONE 'Eastern Standard Time';
Therefore, presumably, you just need to do the same for your column, StartTime, which is also a UTC time:
SWITCHOFFSET(StartTime,0) AT TIME ZONE 'Eastern Standard Time'
If you don't want the timezone portion, then you can convert it back to a different date and time data type:
CONVERT(datetime2(0),SWITCHOFFSET(StartTime,0) AT TIME ZONE 'Eastern Standard Time')

How to get the Time Offset converted to an Int or added to the datetime column (with TSQL)

I have the following script giving me:
Select ENDTIME_UTC AT TIME ZONE 'E. South America Standard Time' as TransactionDate_ESAST
,ENDTIME_UTC as TransactionDate
From Table_CYC
--Results: 2019-11-09 21:02:28.000 -03:00, 2019-11-09 21:02:28.000
However, I would want it either -3 (as an integer for just the offset portion) or 2019-11-09 18:02:28.000, where the hour is subtracted by three.
What would be the best way to go about this?
Thanks,
Yolanda
As currently written you are asserting that the existing value is in Brasilia time and not performing any time zone conversion. Instead, you need to assert that the existing value is in UTC and then convert to Brasilia time.
This is done by calling AT TIME ZONE twice.
SELECT ENDTIME_UTC AT TIME ZONE 'UTC' AT TIME ZONE 'E. South America Standard Time'
The first AT TIME ZONE creates a datetimeoffset from your input datetime asserting that it should be applied with the UTC time zone.
The second AT TIME ZONE then converts from that datetimeoffset to another datetimeoffset with the given time zone.
Note that this is only necessary because your original field is of type datetime (or datetime2, etc.). If instead your field was a datetimeoffset, then your original code would work fine.

Converting UTC time to local time or EU daylight comparision

Select a, b, c, FROM x
JOIN y ON x.x=y.x
AND x.PlannedDateTime BETWEEN y.FromDateTime and y.ToDateTime
Plannedsate time is local time ( e.g. 2018-03-07 14:03:00.000)
FromDateTime is UTC (2018-03-07 14:03:00.000 +01:00) I dont know UTC or daylight in EU
ToDateTime is UTC (2018-03-07 15:27:00.000 +01:00) I dont know UTC or daylight in EU
When I join on these dates as above written query I miss many records. I think due to different time format.
Please provide any solution thanks in advance
As specified in the comments, in SQL Server 2016 or later, you should use AT TIME ZONE to convert a datetimeoffset to a specific timezone. To convert a datetimeoffset to the local time zone of the server, you first have to find it and then you can use it like this:
DECLARE #TimeZone VARCHAR(50)
EXEC master.dbo.xp_regread 'HKEY_LOCAL_MACHINE', 'SYSTEM\CurrentControlSet\Control\TimeZoneInformation', 'TimeZoneKeyName',#TimeZone OUT
SELECT #TimeZone
DECLARE #x DATETIMEOFFSET='2018-03-07 14:03:00.000 +01:00'
SELECT #x AT TIME ZONE #TimeZone
DECLARE #y DATETIMEOFFSET='2018-04-07 14:03:00.000 +01:00'
SELECT #y AT TIME ZONE #TimeZone
On my computer (located in Bucharest, Romania, which is also part of the European Union) the above query returns:
GTB Standard Time
2018-03-07 15:03:00.0000000 +02:00
2018-04-07 16:03:00.0000000 +03:00
As you can see, this takes into account the daylight savings time which would be in effect or not at the specified date.
Instead of the timezone of the server (or if you cannot use xp_regread due to permission issues), you may want to use a specific timezone, for example 'Central Europe Standard Time'.

SQL DateTimes stored in UTC get beginning of day based on offset

This may be the most pathetic question ever asked related to SQL and date/time values, but I could use some help...
Trying to setup a function/job that will run at a specified time or times in eastern, mountain, central, and pacific time zones (in theory other zones would work too). The system will identify which users belong to each timezone and then output data from the system highlighting what they've accomplished for the current day.
Here is my challenge, I know all date/time values are stored on the SQL DB in UTC. I can apply the offset and convert those times to local time zones. Rather than convert tens of thousands of date/time values to local time and make comparisons there, it'd be cleaner (I think) to simply adjust the beginning and ending date/time values of UTC within the stored procedure.
On the west coast it is currently just about 2017-09-30 14:30:00 and in UTC is 2017-09-30 21:30:00, this clearly demonstrates a 7 hour time zone difference right now which means "today" from a user perspective technically started at 2017-09-30 07:00:00 and will end on 2017-10-01 06:59:999 in UTC.
What is the best way of establishing these date/time values for a users beginning of day and ending of day values?
UPDATES
I currently have this code...
DECLARE #InputDate as DateTime
DECLARE #InputEndDate as DateTime
DECLARE #InputDateWithOffset as DateTimeOffSet
DECLARE #InputEndDateWithOffset as DateTimeOffSet
SET #InputDate = '2017-09-28'
SET #InputDateWithOffset = #InputDate AT TIME ZONE 'UTC' AT TIME ZONE 'Pacific Standard Time'
SET #InputEndDate = DATEADD(day, 1, DATEADD(ms, -3, #InputDate))
SET #InputEndDateWithOffset = #InputEndDate AT TIME ZONE 'UTC' AT TIME ZONE 'Pacific Standard Time'
SELECT
#InputDate AS InputDate, #InputEndDate AS InputEndDate,
#InputDateWithOffset AS InputDateWithOffset,
#InputEndDateWithOffset AS InputEndDateWithOffset
Which outputs the following:
The last two columns appear to be correct as it would represent both the beginning of the Input Date and the ending of the Input Date as the Input Date is going to be the local date of the execution...
When I take the #InputDateWithOffset and #InputEndDateWithOffset against my table values with datetimes in UTC, it appears the only dates being returned are those that fall on 2017-09-28 and seems to disregard the comparisons to the Offset date/times.
Your update is mostly correct. However, you're missing a "start of day" operation, which needs to be done in local time.
Consider:
DECLARE #InputStartUTC as DATETIME, #InputEndUTC as DATETIME
DECLARE #InputStartDTO as DATETIMEOFFSET, #InputEndDTO as DATETIMEOFFSET
DECLARE #InputStartDTOatStartOfDay as DATETIMEOFFSET,
#InputEndDTOatStartOfDay as DATETIMEOFFSET
DECLARE #tz as VARCHAR(50) = 'Pacific Standard Time'
SET #InputStartUTC = '2017-09-28 00:00:00'
SET #InputStartDTO = #InputStartUTC AT TIME ZONE 'UTC' AT TIME ZONE #tz
SET #InputStartDTOatStartOfDay = CAST(CAST(#InputStartDTO as DATE) as DATETIME)
AT TIME ZONE #tz
SET #InputEndUTC = DATEADD(day, 1, #InputStartUTC)
SET #InputEndDTO = #InputEndUTC AT TIME ZONE 'UTC' AT TIME ZONE #tz
SET #InputEndDTOatStartOfDay = CAST(CAST(#InputEndDTO as DATE) as DATETIME)
AT TIME ZONE #tz
SELECT
#InputStartUTC as InputStartUTC, #InputEndUTC as InputEndUTC,
#InputStartDTO as InputStartDTO, #InputEndDTO as InputEndDTO,
#InputStartDTOatStartOfDay as InputStartDTOatStartOfDay,
#InputEndDTOatStartOfDay as InputEndDTOatStartOfDay
Also, notice I did not subtract three milliseconds from your end date. Rather than trying to figure out .997 or .999 or whatever, the better approach is to query using a half-open interval. In other words, start <= value AND end > value.