SQL Server Timezone in where clause - sql

I am storing datetime field with UTC time. We have a requirement to filter the records with CST timezone.
I have tried this query:
select id, CreatedOn,
CreatedOn AT TIME ZONE 'UTC' AT TIME ZONE 'Central Standard Time' AS LocalTime
from Status
WHERE CAST((CreatedOn AT TIME ZONE 'Central Standard Time') AS date) = '2018-09-06'
order by CreatedOn desc;
The issue is that it is also bringing those records which were saved on September 5th CST time in the evening when the UTC time was changed to 6th September. What is the correct way to filter out only September 6th records in CST time?

I found an issue with the query, I was missing 'UTC' AT TIME ZONE in the where clause. Here is the correct query which works:
select id, CreatedOn,
       CreatedOn AT TIME ZONE 'UTC' AT TIME ZONE 'Central Standard Time' AS LocalTime from CosmoStatus WHERE CAST((CreatedOn AT TIME ZONE
'UTC' AT TIME ZONE 'Central Standard Time') AS date) = '2018-09-06'
order by CreatedOn desc;

Related

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')

Combining date and UTC time fields in Postgres

I have 2 separate fields for date and time. The time field is stored in UTC time. How can I combine the 2 into a datetime field into local time
Example:
date: 2021-03-08
time in UTC: 23:00
time zone: GMT+8
I would like to get 2021-03-08 07:00 in local time
or even 2021-03-07 23:00 in UTC
Note: Combining the fields is not an option unfortunately.
Need to know your time zone to convert. To convert utc to america/los_angeles time zone:
select '2021-03-08 23:00'::timestamp at time zone 'UTC' at time zone 'america/los_angeles'
you can check out below codes:
If you have a timestamp without time zone column and you're storing timestamps as UTC, you need to tell PostgreSQL that, and then tell it to convert it to your local time zone.
select created_at at time zone 'utc' at time zone 'america/los_angeles'
from users;
To be more concise, you can also use the abbreviation for the time zone:
select created_at at time zone 'utc' at time zone 'pst'
from users;
To see the list of time zones PostgreSQL supports:
select * from pg_timezone_names;
SInce the time difference is 8 hours, try
SELECT '2021-03-08'::date + ('23:00'::time + '8 hours'::interval);
If you want this to work with arbitrary time zones, the query becomes more complicated:
SELECT '2021-03-08'::date
+ ((current_date + '23:00'::time)
AT TIME ZONE 'UTC'
AT TIME ZONE 'Asia/Ulaanbaatar'
)::time;

DateTime conversion and comparison in SQL Query

I have a sql query for pulling a report from a table. The idea is to pull the sum of counts, grouped by day of the week, in the local timezone. Dates in the table are stored in UTC.
SELECT (SUM(t.di1) + SUM(t.di2) + SUM(t.di3) + SUM(t.di4)) AS [ScanCount],
DATEPART(WEEKDAY, t.LocalTime) AS [weekday]
FROM (SELECT di1,
di2,
di3,
di4,
CreatedOnUTC AT TIME ZONE 'UTC' AT TIME ZONE 'Pacific Standard Time' AS LocalTime
FROM tableName
WHERE DeviceId = 649754) t
WHERE t.LocalTime > '03/16/2020 00:00'
AND t.LocalTime < '03/16/2020 23:59:59'
GROUP BY DATEPART(WEEKDAY, t.LocalTime)
ORDER BY DATEPART(WEEKDAY, t.LocalTime);
A query like this should only return a single day of the week count, but it returns 2 days. This obviously has something to do with the difference in time zones, whereas the UTC time contains dates from both 3/15 and 3/16. It seems that the conversion from UTC to Pacific Time works in the output but the UTC values are used in the where clause. How can I do this comparison to the new converted datetimes and not to the original UTC times?
Comparison between datetimeoffset and string literal works in UTC.
Simplest solution will be to convert datetimeoffset to datetime2.
Modify your inner query to:
cast(CreatedOnUTC AT TIME ZONE 'UTC' AT TIME ZONE 'Pacific Standard Time' as datetime2(0)) AS LocalTime

Group by time with timezone conversion in Postgresql

I am working with time data that is currently stores in UTC but I want it to be in PST, which is 8 hours behind. I have a pretty lengthy and involved query, but the only thing I am interested in is the time right now so I have included those parts. I want to convert the times to PST and then group by the date for the last week of data. The query has the following structure:
select
date_trunc('day', time1) AT TIME ZONE 'US/Pacific'
...
where
time1 AT TIME ZONE 'US/Pacific' > now() AT TIME ZONE current_setting('TimeZone') - INTERVAL '168 HOURS'
...
group by date_trunc('day', time1)
This results in the following time groupings. From my understanding, it groups from the 0:00 UTC, which is 16:00 in PST. However, I want the groupby to start at 0:00 PST. How do I do this? Right now, the counts in each group are misleading for each day because they go from 4 pm to 4 pm instead of 12 am to 12 am. For example, Sundays have uncharacteristically high counts because Sunday includes part of Monday's data in the groupby. I would appreciate any input to fix this issue. Thank you.
The answer depends on whether it is a timestamp with time zone or one without:
If it's a timestamp with time zone, you can convert to PST with select time1 AT TIME ZONE 'US/Pacific' and get the date with select date_trunc('day', time1 AT TIME ZONE 'US/Pacific')
If it's a timestamp without time zone stored in UTC that you want to convert, you first have to tell PostgreSQL to interpret it as UTC, then convert it, like so: select (time1 AT TIME ZONE 'Z') AT TIME ZONE 'US/Pacific' and of course you can get the date with select date_trunc('day', (time1 AT TIME ZONE 'Z') AT TIME ZONE 'US/Pacific')
In either case you have to convert time zones before truncating to the day level or you may end up with inaccurate results.

I want to adjust a date for summer/winter time and time zone when insterting it into a table

I have a date and time variable in TABLE_A that is in GMT. I want to insert this date and time into TABLE_B, but I want the insterted value to be adjusted for time zone and summer/winter time.
That is:
INSERT into TABLE_A (ADJUSTED_DATE_AND_TIME)
SELECT GMT_DATE_AND_TIME [Perform proper adjustments here..?]
FROM TABLE_A
Can I do this? In that case, how do I write ?
Thank.
I think you can simply convert the GMT/UTC time. However, you have to take the full region name of your time zone.
SELECT TIMESTAMP '2014-06-10 12:00:00 +00:00' AT TIME ZONE 'Europe/Zurich' AS summer FROM dual;
SUMMER
---------------------------------------
10.06.2014 14:00:00.000000000 +02:00
SELECT TIMESTAMP '2014-12-10 12:00:00 +00:00' AT TIME ZONE 'Europe/Zurich' AS winter FROM dual;
WINTER
---------------------------------------
10.12.2014 13:00:00.000000000 +01:00
Since your source value is data type DATE you have to do following steps.
Cast DATE to TIMESTAMP
Set Time zone of the value using FROM_TZ
Convert the value to new time zone using AT TIME ZONE '...'
Cast the value to DATE
Written in a single statement it is
select
CAST(FROM_TZ(CAST(sy_sttime AS TIMESTAMP), 'UTC') AT TIME ZONE 'Europe/Zurich' AS DATE)
from sy_request
or a bit less clear
select
CAST((CAST(sy_sttime AS TIMESTAMP) AT TIME ZONE 'UTC') AT TIME ZONE 'Europe/Zurich' AS DATE)
from sy_request