I'm looking for a way in SQL Server without using the .NET framework to find out the time in a given time zone, paying attention to daylight savings. However, this method also needs to take account for states (e.g. Arizona) that do NOT follow DST.
There is a workaround if the server is located somewhere that does follow DST - subtract your current time from GMT to get the offset - but I am looking for a more general-purpose solution. I know the .NET framework has ways to do this, but it would be great to avoid having this kind of dependency within this stored procedure.
Thanks!
You could do this in a CLR Stored Procedure. This still is a process from within SQL Server, and is a dependency on the server itself, not any external .Net app that you have to write.
http://msdn.microsoft.com/en-us/library/ms190790.aspx
I typically consider local time stuff to be a view concern, and therefore put it into the web/desktop application. In the database, I work entirely in UTC. So all of the datetime columns in the DB have UTC stored in them, all of the sprocs for reporting and such take UTC, etc. The web/desktop app convert any dates going to/from the user into whatever timezone they have selected.
I know that doesn't really answer your question, but maybe it gives you a different approach?
Related
I am trying to find a way to change SQL server from using UTC time to Local time. This is because I need to be getting Local time when I pull data using ODATA via excel.
Is there a way to configure the SQL server from UTC to local time?
If you have UTC date/time values stored in a datetime, datetime2, or smalldatetime column, you can use AT TIME ZONE to indicate the current value is UTC and to convert the value to the time zone of your choice:
SELECT YourUTCDateTimeColumn AT TIME ZONE 'UTC' AT TIME ZONE 'Pacific Standard Time' AS YourLocalDateTimeColumn
AT TIME ZONE returns a datetimeoffset data type. This can be cast back to the source type if datetimeoffset is problematic for your use case:
SELECT CAST(YourUTCDateTimeColumn AT TIME ZONE 'UTC' AT TIME ZONE 'Pacific Standard Time' AS datetime2(3)) AS YourLocalDateTimeColumn
SQL Server's local timezone is derived from the local operating system. If you wanted to globally affect the timezone that SELECT GetDate() uses, then you can change the time zone of the server.
This is a workaround that is not often recommended to a much larger issue.
Since 2005, the best practice for handling date and time in .Net is to use DateTimeOffset, and this advice became standard in SQL Server 2008. Storing times in DateTime is an anti-pattern that forces a lot of manipulations but worse, it forces a lot of asumptions, for instance how do you know that the value is a local time or UTC, and then which local time zone was used and was it daylight savings or not?
DateTimeOffset provides us with correct sorting and time difference calculations for values that might be entered in different time zones, read more in my blog: Why was DateTime removed from OData v4
If you are querying through an OData API, then you can implement the conversion of timezones in the API logic, or you can manipulate the SQL queries direct, either via middleware, custom serialization or other injection techniques. To go into specifics would however require you to post your associated code.
This answer from #Dan Guzman shows some examples of using AT TIME ZONE in your SQL queries directly, which was introduced in SQL Server 2016. You might also be interested in TODATETIMEOFFSET() or SWITCHOFFSET() but implementing these functions still requires assumptions about the specific time zone to either be hardcoded into the API logic or to be passed through from the client.
It can be done, but when consuming the data in Excel, via an OData API from an SQL database there are multiple points where the conversion logic can be implemented, therefor multiple plausible solutions.
Don't forget, you could apply this time zone logic as a transformation step inside Excel after the data has been retrieved. I hope this post inspires you to research a bit further and to choose a specific pathway. Then if you get stuck, please post a more focused question that details your specific attempt. We are here to help ;)
Lets say Machine A is app server where I am running sql query.
Machine B where sqlserver is setup. They are in different time zone. eg Machine A is in IST and Machine B in CST
Now I want to run sql query in Machine A to get its current time rather than sql server current time.
For eg. I tried all these functions but they return Machine B(sql server current time)
SELECT SYSDATETIME()
,SYSDATETIMEOFFSET()
,CURRENT_TIMESTAMP
,GETDATE()
I can fetch Machine A current time by Java and pass it to sql query but is there any way to fetch by sql query itself??
No. And it makes sense because SQL will send your command to the server. As such - you expect the SQL Server to then magically go to your machine and execute code?
The general approach is that all local processing (app server level) is finished when the SQL gets sent to the server (as a string).
Also good coding standards would ask you what you care (outside of clocks not being in sync) as all application internal timestamps are in UTC anyway (regardless of timezone of the server) and the timezone conversion is only done on the UI level code.
So, no - what you want can not be done, and in most applications is not needed as they handle the problem outside the database.
You have to use the DateTime Class tools of other languages.
You don't query from a Database the Current Time because it is not a stored data, or a storable ones.
There is no solution if you do it in the SQL, you really have to do it in a language like Java or C# because they have access to the Time of the machine, since the program is intended to run in a machine, therefore they have acess to it.
I have been working with oracle DB for a long time and have been storing dates without bothering about timezone.
But now we have a issue where client and server are in different timezones and we need to perform date/time conversion according to timezone. This has opened up lots of questions now:
Should we always store date/time along with its timezone or not?
I am asking this because if servertimezone changes then my data will be corrupted.
If oracle db server is located in a particular region then should it always run on local timezone? Is there any standard for this?
My second point is in relation to DR database servers which are located in different regions but have same data as prod DB. If timezones are not same for both DB then we are in trouble.
To be able to show clients date in their timezone you need some offset.
for example, your server runs in US EDT and you saved time like that for years. All your data is saved that way. So, you need to create a field, where you store offset for each user. You will then need to apply this offset to each date/time field on select. How you do this, I have no idea - because I have no idea how you use your data. Is it just a select statement, a report, or a website? But if this was an application, client would load user info including offset. For example, user in US EDT will have offset of 0 in your case. And then, any date/time field that is requested from db should get offset value applied. Of course, since your application was not designed for this from the beginning, it might will take some good effort.
I'm using an sql server 2005 hosted in the states. Soon we will move the db to Europe.
I'd like to update the dates in the db to take into account the timezone difference.
Is there a good way to do this?
Or is it just a case of looping through the dates and adding the timezone offset?
Does it really need to change because it was physically moved? If you're supporting global applications I would store all my date/time information in GMT and translate to local on the client side.
I think you should be saving the date/times in database in a constant timezone it can be either GMT (because it is pretty simple to transform it into other timezones) or the current timezone of the server if it is not GMT.
Th eonly reason the later option makes sense is that you use the CURDATE function to insert/filter records from the database otherwise GMT is the best option.
You can try using DATEDIFF with DATEADD but due to DST this will not always give the accurate time (off by 1 hour in some cases).
There is a known limitation in SQL Server 2005 about timezone conversions, please refere to the following link for more information:
http://connect.microsoft.com/SQLServer/feedback/ViewFeedback.aspx?FeedbackID=308563
I work with legacy systems that have tens of thousand of lines of stored procedure code, where many of the stored procedures are obsolete and not used anymore. There doesn't seem to be a way to check execution history, so my question is if it might be a good idea to start each stored procedure by inserting a row into a table that keeps records of the execution?
could be very simple like:
insert into
executionHistory (
name,
date
)
select
'spName',
getdate()
-- then rest of procedure
I imagine this could be very useful for doing cleanups of old unused code, and might also be handy when trying to decide where to optimize. I mean it's better to shave 10 seconds off execution time on a procedure that is executed 50 times a day, than saving 10 minutes execution time on a procedure that is only used once a year.
There is a tracing option (SQL Profiler) in SQL server. you could take a trace of a days SQL activity and see which sprocs are executed there.
This will give you a good idea of where to focus your optimisations.
because you're using sql server 2008 i wouldn't do what rwmnau suggest because this would mean you have to modify all your stored procedures.
SQL Server 2008 introduces a feature called Extended Events and SQL Server Auditing based on them. Extended events are high performance tracing system.
by using SQL Server Auditing you can trace your system withouth the overhead of sql trace.
I think your idea is simple enough and would accomplish your goal. Though it would involve modifying every SP, it's the route I would choose. Then you can ensure that you're getting an accurate recording of all activity on the database.
Another poster suggested you do a trace - while this works for short periods, it's only going to catch the time you're watching. You'd have to make sure you traces across any important, high-traffic periods, like month-end financial closing, and even then, you're missing other times you don't think are that big a deal, so you're being subjective.