I have a timezone name like America/Vancouver saved in a SQL Server database.
I want to get the UTC offset from the timezone name in SQL like America/Vancouver has -08:00 offset. So how can I write a query in SQL?
Your help is much appreciated
Unfortunately SQL Server doesn't yet support IANA time zone identifiers (like America/Vancouver) directly. For now, the best option is to convert from the IANA identifier to a corresponding Windows time zone identifier in your application layer, and store that in your SQL Server.
For example, if you are running .NET in your application layer you can use my TimeZoneConverter project:
string tz = TZConvert.IanaToWindows("America/Vancouver");
// Result: "Pacific Standard Time"
Then you can use the AT TIME ZONE function in your SQL Server code:
SELECT sysdatetimeoffset() AT TIME ZONE 'Pacific Standard Time'
The above will give you the current date, time, and offset in the given time zone, which you can use as the basis for your query against the user's availability (mentioned in the question comments).
Keep in mind that the offset adjustment will be different depending on whether daylight saving time is in effect or not. Despite the word "Standard" in the Windows identifier, DST is indeed taken into account where applicable.
Alternatively, if for some reason you must do this entirely in SQL Server without converting to Windows time zones, then you will need to rely on projects such as my SqlServerTimeZoneSupport project. That one is a bit old and not very well maintained, so I recommend against that approach if you can help it.
Use DATEPART with TZ parameter. Example :
SELECT DATEPART(tz, (CAST('2021-01-01' AS DATETIMEOFFSET) AT TIME ZONE 'Central European Standard Time'));
The result is in minutes.
Related
I want to use UTC timestamps exclusively in an MSSQL database. When writing the current timestamp I can use system methods like GETDATEUTC and we have agreed with suppliers that timestamps sent from external sources will also be provided as implicit UTC - but when writing these to the DB do I need to tell MSSQL that it is a UTC date somehow? Or is it my responsibility to know what timezone I'm using?
To provide an answer, in short Neither Datetime nor Datetime2 encodes timezone information, only the raw date/time data specified. It is up to the developers/DBAs/users to agree what the data means.
We use a PLM software called "Aras Innovator" and need to store a date as a custom item property. The software uses Microsoft SQL Server to store its data and accessing properties on the database level is officially supported.
However, our issue is that the software only supports datetime, not date.
And dates are stored in UTC - so when we store "2020-01-01" from a client in Central Europe, it becomes "2019-12-31 23:00" or so in the database (1 hour before midnight on the day before). And queries checking for ">= 2020-01-01" then consequently fail to find these rows.
The software manufacturer says:
There is no standard feature for storing only the month and day; a
quick option may be to store it as a string instead and do
programmatic validation on the inputted string if required.
Regarding direct SQL queries, all dates are stored in UTC for
compatibility with multiple time zones. They are automatically
converted when accessed via the standard API. When accessing direct
with SQL, you can use the function ConvertToLocal described in the
Aras Innovator 11.0 - Configuring Internationalization guide on the CD
Image, section 5.3:
SELECT item_number, innovator.ConvertToLocal(created_on, 'Eastern
Standard Time') AS CreatedOn FROM innovator.Document
ConvertFromLocal can be used for specifying dates you wish to query
against rather than requiring those dates to be sent in UTC.
I'm not convinced that working with string would be a good solution.
But not convinced that their "ConvertTo/FromLocal" functions would be a good solution either.
Surely there must be some other way to handle this directly in SQL Server?
SQL Server 2016 introduced the AT TIME ZONE statement.
Consider:
SELECT CONVERT(date, TheDateTime AT TIME ZONE 'UTC'
AT TIME ZONE 'Central Europe Standard Time')
The above will first convert TheDateTime field from a datetime or (datetime2) to a datetimeoffset type with zero offset (UTC). Then it will convert it to the Central Europe Standard Time zone, and lastly will convert it to a date type, removing any time information.
As far as your statement:
... >= 2020-01-01" then consequently fail to find these rows.
You should consider instead converting the opposite direction such that you are querying against UTC time - which would be sargable. For example:
SELECT ...
WHERE TheDateTime >= CONVERT(datetime,
'2020-01-01' AT TIME ZONE 'Central Europe Standard Time'
AT TIME ZONE 'UTC')
Of course, you could do the whole right-side of the expression ahead of time and use a local variable instead. Likewise, if you are calling this query from an application, you could convert to UTC in your application code and not have to bother doing it in SQL Server at all.
We're working on a IOS app using Microsoft's Azure Mobile Services. The web GUI creates date-time as DateTimeOffset fields, which is fine. But when we have the mobile put datetimes into the database, then read them from the database, via Entity Framework, we're seeing them adjusted to UCT. (We see the same thing when we view the records in SSMS.)
I've always been frustrated by the lack of timezone support, in SQL's standard datetime types, and I'd thought that DateTimeOffset would be better. But if I wanted my times in UTC, I'd have stored them in UTC. If a user enters a time as 3:00 AM, CST, I want to know he entered CST. It makes as little sense to me to convert it to UTC, and throw away the offset, as it did to assume that 3:00 AM CST and 3:00 AM PDT were the same.
Is there some kind of database configuration I can do to keep the Azure database from storing the dates in UTC?
The issue is that at some point in Azure Mobile Services, the property is converted to a JavaScript Date object, which cannot not retain the offset.
There are a couple of blog posts describing this issue, and possible workarounds:
https://blogs.msdn.microsoft.com/carlosfigueira/2013/05/13/preserving-date-time-offsets-in-azure-mobile-services/
http://michele-colombo.it/2014/11/azure-mobileservices-how-to-properly-save-datetimeoffset-with-offset/
Essentially, they both take the same approach of splitting out the offset into a separate field. However, looking closely at these, they both make a crucial mistake:
dto.DateTime.ToUniversalTime()
Should actually be:
dto.UtcDateTime
The DateTime of a DateTimeOffset will always have DateTimeKind.Unspecified, and thus ToUniversalTime will assume the source is local, rather than using the offset of the DTO.
There are a few other similar errors I see in the code in these posts, so be careful to test thoroughly. However, the general approach is sound.
We're using a Node.js backend and noticed the same thing with DATETIMEOFFSETs read from our SQL Server database being returned in UTC regardless of the offset. Another alternative is to convert the DATETIMEOFFSET at the query-level so that it is outputted as a string with the timezone information. The following converts a DATETIMEOFFSET(0) field to the ISO8601 format; however, other possible styles can be used as documented here:
SELECT CONVERT(VARCHAR(33), [StartDate], 126) AS [StartDate] FROM [Products];
The new output is now: "2016-05-26T00:00:00-06:00" instead of "2016-05-26T06:00:00+00:00"
Of course, this means that the client must serialize the string into their respective format. In iOS, the ISO8601 library can be used to read the output as either a NSDateComponents or NSDate.
One benefit of this approach is that any database-level checks or triggers can do date comparisons using the DATETIMEOFFSET instead of trying to take into account a separate offset column with a basic DATETIME.
In my SQL Server 2008 R2 database, I have a LastHWScan column (datetime) and a TimzoneOffset column (int).
The LastHWScan column stores the datetime that is local to the workstation being scanned. The TimezoneOffset column stores the timezone offset as either a positive or negative number of minutes. Dallas is -300, Bucharest is 180.
How can I, in a SQL query, convert these datetime from various timezones to Dallas time?
Would it be easier to convert everything to UTC and then convert it to Dallas time?
In my SQL Server 2008 R2 database, I have a LastHWScan field (datetime) and a TimzoneOffset field (int).
That's fine, though you might also consider that SQL Server has a datetimeoffset field which can combine these into a single type.
Or, if the time zone offset is unimportant to your scenario, you might consider storing just the equivalent UTC value in a datetime or datetime2 field.
The LastHWScan field stores the datetime that is local to the workstation being scanned. The TimezoneOffset field stores the timezone offset as either a positive or negative number of minutes. Dallas is -300, Bucharest is 180.
Be careful here. The offset should be aligned to the specific date and time. Dallas may be -300 (UTC-5) in the summer when DST is in effect, but most of the year it's -360 (UTC-6). Likewise, Bucharest alternates between 180 (UTC+3) and 120 (UTC+2).
Do not detach the offset from the date/time, or assume that the offset for one location and date/time is valid for all possible other date/time values within that location.
How can I, in a SQL query, convert these datetimes from various timezones to Dallas time?
That's difficult to do in SQL, because you have to account for the daylight saving time rules of Dallas. Other DBs have functions like CONVERT_TZ, but SQL Server doesn't have anything like that built in. You can write your own functions, or you might consider my SQL Server Time Zone Support project.
Would it be easier to convert everything to UTC and then convert it to Dallas time?
"Easier" is subjective. Many people prefer storing values in UTC. Storing them in a datetimeoffset (or in two fields like you have done) is fine - and it's preferable when the local time is important in the context of the application domain (See DateTime vs DateTimeOffset). The only thing that you shouldn't do is drop the offset and store only local time.
Even if you did convert to UTC, that wouldn't help with the conversion. Though you've properly identified a specific instant in time, you still have to account for time zone rules of the destination time zone. If you only need US Central time, you might consider hardcoding the transition rules and offsets into a UDF or stored proc. Otherwise, use my time zone integration project with the "America/Chicago" time zone id.
Example:
SELECT Tzdb.UtcToLocal(dateadd(mi, -offset, localdatetime), 'America/Chicago')
Note the negation of the offset to convert from local back to UTC before calling the custom UDF.
I transfer data from one SQL Server to another using SELECT * INTO .... statement (in Management Studio). Both databases have different timezone settings.
Is it possible to adjust all date/time fields to different timezone automatically? Maybe some query parameters or connection settings?
Since you are on SQL Server 2008, you could use the built-in functionality of the DATETIMEOFFSET datatype, and the SWITCHOFFSET function.
You could do something like:
INSERT INTO dbo.YourTargetTable( ...... )
SELECT
SWITCHOFFSET(TODATETIMEOFFSET(YourSourceTime, '+04:00'), '-09:00'),
.......
TODATETIMEOFFSET converts your "regular" date without any timezone information into a DATETIMEOFFSET type with a time zone (of your source location), and then you can apply a SWITCHOFFSET call to that value to "switch" your date/time to your target location's time zone.
This can be done in the scope of the INSERT....SELECT statement - no separate "row-by-row" updating necessary.
I think this will be helpful, please follow the link:
Effectively Converting dates between UTC and Local (ie. PST) time in SQL 2005
Shortly, you do need to build time zone and DST tables to get some help with time zones.
Thanks