Change timestamp without effect date - sql

I am using SSMS and I have a table with date/time stored in a column. What i need to do is change the time but leave the date.
Example: 2020-07-28 00:00:00. I need to change the timestamp 00:00:00 to 23:59:00 without changing the date for the whole column.
CPRDate -- Column Header
2020-07-28 00:00:00
2020-01-01 00:00:00
2017-01-01 00:00:00

You can just add them together -- as datetimes:
select cprdate + convert(datetime, convert(time, '23:59:00'))
This construct is clearly documented and supported by SQL Server:
The plus (+) and minus (-) operators can also be used to run arithmetic operations on datetime and smalldatetime values.
You can use the same construct in an update if you want to change the stored value.
If cprdate is a date, you need to convert it to a datetime for this to work.

You could add subtract one minute and add a day to achieve this, i.e.
update MYTABLE SET CPRDate = DATEADD(day, 1, DATEADD(minute, -1, CPRDATE));
Here's a SQL Fiddle to show it working.

Related

SQL Server 2019 - add day in date with time component

I want to add 1 day to date with time component.
My date is say for eg.
2020-09-10 18:30:00.000'
and I want to add 24 hours i.e expected output is
2020-09-11 18:30:00.000
I wrote SELECT DATEADD(day, DATEDIFF(day, 0, '2020-09-10 18:30:00.000'), 1) but this does not show the time component.
How to add date with time component?
SQL Server is really flexible about recognizing date formats, and will happily understand your string as a date if you put in within a date function. So, no need for explicit conversion from string to date, you can just do:
dateadd(day, 1, '2020-09-10 18:30:00.000')
Drop the datediff() in your attempt. And according to the documentation, the date is the third argument of the dateadd() function.
select dateadd(day, 1, convert(datetime, '2020-09-10 18:30:00.000') );
Output:
2020-09-11 18:30:00.000

UTC and offset date time compare in sql server

I am storing UTC datetime in Database
e.g.
2018-06-05 11:37:00.000 (UTC)
2018-06-05 17:07 (+5:30 India standart time)
I am having offset as :
offset as +02:00
How can I compare in sql query that now offset time matched ?
e.g.
2018-06-05 13:37:00.000
My issue is X (IST) date time converted to UTC and now I want to covert to different time zone (Y)
The following functions helped me to resolve the issue:
1. SWITCHOFFSET
2. TODATETIMEOFFSET
SELECT GETDATE()
SELECT SWITCHOFFSET(GETDATE(), '+05:30')
SELECT CONVERT(VARCHAR(19), SWITCHOFFSET(TODATETIMEOFFSET(GETDATE(), '+05:30'),'+00:00'), 120)
SELECT GETUTCDATE()
If I understand your question correctly, you can use the DATEADD function to calculate the new datetime based on the UTC datetime and the offset
For example:
2 hours = 120 minutes
DATEADD(minute, 120, '2018-06-05 11:37:00.000')
Or using hours
DATEADD(hour, 2, '2018-06-05 11:37:00.000')
You can also go the other way using negative numbers
You don't have to use a literal value, you can supply a column name to parameter 3 for use in a query and also use this expression as part of a where clause
Here's a cheat sheet for the DATEADD function:
https://learn.microsoft.com/en-us/sql/t-sql/functions/dateadd-transact-sql?view=sql-server-2017

Extract Date And Hour Only From Date Time Field

I am running SQL Server 2008 and I have a datetime field, from this field I only want to extract the date and hour. I tried to parse out using datepart() but I think I did it incorrectly as when I attempted to string the two back together I got a number value. What I attempted was
Select Datepart(YEAR, '12/30/2015 10:57:00.000') +
Datepart(HOUR, '12/30/2015 10:57:00.000')
And what was returned was 2025 What I want to see returned is
12/30/2015 10:00:00.000
You could use DATEADD and DATEDIFF:
DECLARE #d DATETIME = '12/30/2015 10:57:00.000';
SELECT DATEADD(second,DATEDIFF(second,'1970-01-01',#d)/3600*3600 , '1970-01-01')
-- 2015-12-30 10:00:00
LiveDemo
How it works:
Get seconds difference from 1970-01-01
Divide by 3600 (integer division so the part after decimal point will be skipped)
Multiply by 3600 to get value back to full hours
Add calculated seconds number to 1970-01-01
With SQL Server 2012+ the neat way is to use DATETIMEFROMPARTS:
SELECT DATETIMEFROMPARTS(YEAR(#d), MONTH(#d), DAY(#d), DATEPART(HOUR, #d),0,0,0)
LiveDemo2

SQL Server DateTimeOffset matching same "day"

My application needs to collect "Tuesday's" purchases for all locations world wide, where "Tueday" is the location's Tuesday (regardless of time zone). And if the user needs to re-run the report next week, I need to still get "Last Tuesday's" data. All of our data is stored using DateTimeOffset.
So
9/4/12 00:00:00 -7 through 9/4/12 23:59:59 -7
must MATCH
9/4/12 00:00:00 +11 through 9/4/12 23:59:59 +11
when I am executing my WHERE clause.
I can't convert to UTC in the WHERE clause because that will pick up the data for "Tuesday" in London (depending on DST), not the location's Tuesday.
I tried converting from DateTimeOffset to DateTime, but that seems to convert to UTC. (In my tests, passing 9/1/12 through 9/30/12 picked up 8/31/12 data.)
Is there a trick to doing something like this with TSQL?
Thanks!
IMHO
DateTimeOffset = DateTime+Offset(from UTC)
So your data is already representing Client's Local date and time. Just cast it to DateTime and you will get the client's local Date and time.
But in-case if you want to add the Offset to the datetime and want the resultant Datetime then
DECLARE #PurchaseDate DATETIMEOFFSET(7) = CAST('2007-05-08 12:30:29.1234567 +5:00' AS datetimeoffset(7))
SELECT CAST(SWITCHOFFSET (#PurchaseDate , '+00:00') AS DATETIME)
have a look at this blog for further info.
http://blogs.msdn.com/b/bartd/archive/2009/03/31/the-death-of-datetime.aspx
When casting a DATETIMEOFFSET as DATETIME it takes the date and time as offset in the value and simply drops the time zone. The same is true when casting as DATE or TIME. So, I think you can simply cast the column as DATE and compare that to the date-only value you wish to match:
DECLARE #targetDate DATETIME2 = '2012-09-04' --Or we could use DATE here
SELECT [PurchaseId], [PurchaseTime], CAST([PurchaseTime] AS DATE) AS "PurchaseDate"
FROM [Purchases]
WHERE CAST([PurchaseTime] AS DATE) = #targetDate
I'm not sure how efficient this will be (hopefully not bad if the provider is truly clever--which SQL Server likely would be), but you might improve it by bounding the original column value as well:
DECLARE #targetDate DATETIME2 = '2012-09-04' --DATETIME2 so we can adjust by hours
SELECT [PurchaseId], [PurchaseTime], CAST([PurchaseTime] AS DATE) AS "PurchaseDate"
FROM [Purchases]
WHERE CAST([PurchaseTime] AS DATE) = #targetDate --Keep only the local-date matches
AND [PurchaseTime] >= DATEADD(hh, -14, #targetDate) --Up to 14-hour time zone offset
AND [PurchaseTime] <= DATEADD(hh, 38, #targetDate) --24 hours later plus 14
This should efficiently index down to the set of possibilities and then filter properly on the conversion to the local date. Note that time zone offsets can be up to 14 hours (New Zealand is furthest I know at +13:00, but they can go to +/- 14:00 according to MSDN) and the #targetDate will be at the start of the day, so it compares back to 14 hours earlier and 24+14=38 hours later. DATETIME2 has the same range and precision as DATETIMEOFFSET, so it's better for this purpose than the original DATETIME (but it may also work okay with DATETIME instead).

MySQL "between" clause not inclusive?

If I run a query with a between clause, it seems to exclude the ending value.
For example:
select * from person where dob between '2011-01-01' and '2011-01-31'
This gets all results with dob from '2011-01-01' till '2011-01-30'; skipping records where dob is '2011-01-31'. Can anyone explain why this query behaves this way, and how I could modify it to include records where dob is '2011-01-31'? (without adding 1 to the ending date because its been selected by the users.)
From the MySQL-manual:
This is equivalent to the expression
(min <= expr AND expr <= max)
The field dob probably has a time component.
To truncate it out:
select * from person
where CAST(dob AS DATE) between '2011-01-01' and '2011-01-31'
The problem is that 2011-01-31 really is 2011-01-31 00:00:00. That is the beginning of the day. Everything during the day is not included.
select * from person where dob between '2011-01-01 00:00:00' and '2011-01-31 23:59:59'
Is the field you are referencing in your query a Date type or a DateTime type?
A common cause of the behavior you describe is when you use a DateTime type where you really should be using a Date type. That is, unless you really need to know what time someone was born, just use the Date type.
The reason the final day is not being included in your results is the way that the query is assuming the time portion of the dates that you did not specify in your query.
That is: Your query is being interpreted as up to Midnight between 2011-01-30 and 2011-01-31, but the data may have a value sometime later in the day on 2011-01-31.
Suggestion: Change the field to the Date type if it is a DateTime type.
Hi this query works for me,
select * from person where dob between '2011-01-01' and '2011-01-31 23:59:59'
select * from person where DATE(dob) between '2011-01-01' and '2011-01-31'
Surprisingly such conversions are solutions to many problems in MySQL.
In MySql between the values are inclusive therefore when you give try to get between '2011-01-01' and '2011-01-31'
it will include from 2011-01-01 00:00:00 upto 2011-01-31 00:00:00
therefore nothing actually in 2011-01-31 since its time should go from 2011-01-31 00:00:00 ~ 2011-01-31 23:59:59
For the upper bound you can change to 2011-02-01 then it will get all data upto 2011-01-31 23:59:59
You can run the query as:
select * from person where dob between '2011-01-01' and '2011-01-31 23:59:59'
like others pointed out, if your dates are hardcoded.
On the other hand, if the date is in another table, you can add a day and subtract a second (if the dates are saved without the second/time), like:
select * from person JOIN some_table ... where dob between some_table.initial_date and (some_table.final_date + INTERVAL 1 DAY - INTERVAL 1 SECOND)
Avoid doing casts on the dob fiels (like in the accepted answer), because that can cause huge performance problems (like not being able to use an index in the dob field, assuming there is one). The execution plan may change from using index condition to using where if you make something like DATE(dob) or CAST(dob AS DATE), so be careful!
Set the upper date to date + 1 day, so in your case, set it to 2011-02-01.
select * from person where dob between '2011-01-01' and '2011-01-31' or dob like' 2011-01-31%'
Just add or <<column>> like "date%".