Conversion failed date and/or time from character string - sql

the output is a combination from two column and need to convert into date. Data source is numeric. The code works well for the first 100,000 and and error occur after 409,560. Error as "Conversion failed when converting date and/or time from character string."
SELECT
CASE WHEN LEN(OR6) = 6 THEN
CAST(CONCAT(SUBSTRING(CONVERT(VARCHAR(10),ORT),1,4),SUBSTRING(CONVERT(varchar(10),OR6),3,2),SUBSTRING(CONVERT(varchar(10),OR6),1,2))AS DATE)
WHEN LEN(OR6) = 5 THEN
CAST(CONCAT(SUBSTRING(CONVERT(VARCHAR(10),ORT),1,4),SUBSTRING(CONVERT(varchar(10),OR6),2,2),'0',SUBSTRING(CONVERT(varchar(10),OR6),1,1))AS DATE)
ELSE NULL
END AS ORI_MAT_DT ,DATE1 = OR6 ,DATE2 = ORT
FROM DATETABLE
This is the original source database:
ROW OR6 ORT
409,559 10611 2011152
409,560 50618 2018156
409,561 10615 2015152
409,562 50618 2018156
EXPECTED RESULT:
ORI_MAT_DT DATE1 DATE2
2001-08-15 150801 2001227

You can use a little math to get the values you want from the numeric values in OR6 and ORT, and then use DateFromParts to construct the date:
Source data:
DECLARE #Date1 numeric(10,2) = 150801,
#Date2 numeric(10,2) = 2001227
Query:
SELECT DATEFROMPARTS(
#Date2 / 1000, -- Get the year
(#Date1 % 10000 - #Date1 % 100) / 100, -- Get the month
#Date1 / 10000 -- Get the day
) As Date
Result:
Date
2001-08-15
The DateFromParts functions takes int values representing the year, month, and day and construct a Date object. Since it takes int, SQL Server will implicitly convert the numeric values you get from the calculations to int by truncating the decimal part.

Related

DateTime Conversions Issue

My table in the DB has the following format yyyy-mm-dd HH:MM:SS. but the required format for a varchar data type is dd-mm-yyyy HH:MM:SS. when I change this in the query below the code runs but it returns nothing as the table date format doesn't match the varchar data type.
I assume it's a simple data conversion but I'm quite new to this and not sure on how to get around it.
DECLARE #LastxDays TABLE (DateForReport datetime)
DECLARE #DateForReport datetime
DECLARE #Results TABLE (DateForReport DateTime,
Currency VARCHAR(20),
TotalTransactionsIn Decimal(10,2),
TotalTransactionsOut Decimal(10,2),
TotalBalances Decimal(10,2))
-- SET initial date
SET #DateForReport = CAST('26-05-2022 17:00:00' as DATETIME)
PRINT #DateForReport
-- Add a row for each day of the year up to yesterday
WHILE(#DateForReport < dateadd(dd,-1, getdate()))
BEGIN
INSERT INTO #LastxDays VALUES (#DateForReport)
SET #DateForReport = DATEADD(day, 1, #DateForReport)
END
my table result is the following:
|Date | Name |Transaction in |Transaction out|
|2022/26/05|***** |***** |***** |

TSQL Datetime conversion looses a period of time

i'm playing around with a MsSQL Server for some days now and stumbled upon a strange behaviour when converting a datetime to/from a decimal.
SELECT [date] = GETDATE()
, [as decimal] = CAST(GETDATE() AS decimal)
, [from decimal] = CAST(CAST(GETDATE() AS decimal) AS datetime)
, [as float] = CAST(GETDATE() AS float)
, [from float] = CAST(CAST(GETDATE() AS float) AS datetime)
-- should be: 2009-08-15
, [from stored float] = CAST(CAST('40039.9583333333' AS float) AS datetime)
When i convert a datetime without adding anything specific the decimal will be handled as i would define it decimal(18, 0). So there is a data loss in some way.
If i directly convert a float back to datetime which was converted from a datetime (as shown in line 7 of my query) everything is fine.
But when i load a value from a database table, for example 40039.9583333333 which definitely was calculated from a user input (2009-08-15) and convert it back to a datetime, it'll add one day.
I wasn't able to find anything specific for this time loss.
Is somebody able to describe the problem behind this strange behaviour?
And, if possible: add an example on how to do those conversions correctly?
Thanks.
I used the values you specified '2009-08-15' and converted it to both decimal and float, which resulted in a value of 40038 for both. I used this value to convert back to datetime and both the decimal and float returns '2009-08-15 00:00:00.000'.
The value 40039.9583333333 results in, as Renan just posted :), '2009-08-16 22:59:59.997'.
I would question whether it was 'definitely was calculated from a user input (2009-08-15)' because that does not appear to be the case. There is more to it than shared.
-- Microsoft SQL Server 2014 - 12.0.4100.1 (X64)
DECLARE #dt datetime = '2009-08-15'
SELECT CAST(#dt AS decimal) -- 40038
SELECT CAST(#dt AS float) -- 40038
DECLARE #dec1 decimal = 40038;
SELECT CAST(#dec1 AS datetime) -- 2009-08-15 00:00:00.000
DECLARE #flo1 float = 40038;
SELECT CAST(#flo1 AS datetime) -- 2009-08-15 00:00:00.000
DECLARE #dec2 decimal = 40039.9583333333;
SELECT CAST(#dec2 AS datetime) -- 2009-08-17 00:00:00.000
DECLARE #flo2 float = 40039.9583333333;
SELECT CAST(#flo2 AS datetime) -- 2009-08-16 22:59:59.997
What was your input source into the DB? The underlying issue could be the starting reference point for the date.
As an example: From reading online, in Excel the date value '1900-01-01' is equal to 1 numerically.
However, in SQL Server the date value '1900-01-01' is equal to 0 numerically.
SELECT CAST(CAST('1900-01-01' AS DATETIME) AS FLOAT)
In SQL Server 40039.9583333333 is the result of SELECT CAST(CAST('2009-08-16 23:00' AS DATETIME) AS FLOAT)
You should check the inputs. Check which scale/code is being used to calculate the value that is stored on your table.

SQL Compare INT to GETDATE

I'm having trouble figuring this out and have tried everything on here. I know it's simple...
Our dates are stored as int in the table. EX 20130409. How do I get SQL to return dates that are less than today's date?
I've been using different combinations of cast and convert but keep getting either overflow errors or conversion failed.
Here is some recent code:
SELECT
DBO.SPSYS07.LOC_CODE,
CONVERT(DATETIME,CAST(DBO.SPSYS07.REQ_D_DATE AS CHAR(8)),101) AS [CONVERTED_REQ_DATE],
DBO.SPSYS07.REQ_D_DATE
FROM DBO.SPSYS07
WHERE SPSYS07.SHIP_DATE <= convert(int,convert(varchar(8),getdate(),112))
Try declaring today's date and using that
Declare todaysDate date
Set todaysDate = getdate()
Then convert todaysDate to a string, then remove '-' between year, month and days, and then....
Select..... Where shipdate <= todaysDate
You just need to change the '20130101' for your int value.
DECLARE #date date
SELECT #date = CONVERT(date, CAST('20130101' AS CHAR(12)), 112)
SELECT * FROM yourTable where #date < getdate()
regards

SQL: Using DATEADD with bigints

I have some SQL to convert javascript dates to SQL dates which works great. However, I've encoutered some data which is too large and is causing an exception:
Arithmetic overflow error converting expression to data type int
Here is the SQL in question:
DATEADD(MILLISECOND, cast(569337307200000 as bigint) % 1000, DATEADD(SECOND, cast(569337307200000 as bigint) / 1000, '19700101'))
I am running this on SQL Server 2008.
Just do the problematic DATEADD in two steps, starting with a coarser time unit (seconds, minutes, hours etc.), then dropping back to the fine grained one for the remainder.
Avoid going to the level of weeks and months though as that would require actual calendar calculations and we would prefer the system to handle that.
Example below needs to calculate a start time given a (possibly) large current duration in milliseconds.
-- large durations can overflow the integer argument needed for DATEADD
-- so do as two steps subtracting minutes (60000ms) and then remaining milliseconds.
DATEADD(ms, -large_duration_ms%60000, DATEADD(minute, -large_duration_ms/60000, GETDATE()))
One way I got around the Integer overflow issue was to subtract a more recent date from the microtime unix time stamp.
DATEADD(s, (CreationTimeStamp/1000-1384128000), '2013-11-11') AS CreateDate,
This will not fix the OP's problem because they will still overflow the max on the date column.
According to MSDN, in DATEADD (datepart , number , date )
number is an expression that can be resolved to an int that is added
to a datepart of date. User-defined variables are valid. If you
specify a value with a decimal fraction, the fraction is truncated and
not rounded.
Also notice that even if you give number as an integer, depending on your date & datepart, it could overflow the max range of the date which is 31-12-9999 for sql server 2008
Number has to be an integer. Here is a Test Demo
I had the same problem and I wanted to be meet the datetime range of mssql
Minimun datetime: 1753-01-01 00:00:00.000 (-6847804800)
Maximum datetime: 9999-12-31 23:59:59.997 (253402300799)
To achieve this the only solution I found was to loop to use DATEADD with int range values.
So based on this answer: https://stackoverflow.com/a/2904294/687490
CREATE FUNCTION dbo.fn_ConvertToBigDateTime (#Datetime BIGINT)
RETURNS DATETIME
AS
BEGIN
DECLARE #result datetime = Convert(datetime, '01/01/1970');
DECLARE #LocalTimeOffset BIGINT
,#AdjustedLocalDatetime BIGINT
,#MinIntValue INT
,#MaxIntValue INT
,#RemainingSeconds BIGINT;
-- define int limit
SET #MinIntValue = -2147483648;
SET #MaxIntValue = 2147483647;
-- compute the datetime with the offset
SET #LocalTimeOffset = DATEDIFF(second,GETDATE(),GETUTCDATE())
SET #AdjustedLocalDatetime = #Datetime - #LocalTimeOffset
-- going to the future
WHILE(#AdjustedLocalDatetime>#MaxIntValue)
BEGIN
SET #AdjustedLocalDatetime = #AdjustedLocalDatetime - #MaxIntValue;
SELECT #result = Convert(datetime, dateadd(ss, #MaxIntValue,#result));
END
-- going back in the past
WHILE(#AdjustedLocalDatetime<#MinIntValue)
BEGIN
SET #AdjustedLocalDatetime = #AdjustedLocalDatetime - #MinIntValue;
SELECT #result = Convert(datetime, dateadd(ss, #MinIntValue,#result));
END
RETURN (SELECT DATEADD(second,#AdjustedLocalDatetime, #result))
END;
You can then test the function with :
select dbo.fn_ConvertToBigDateTime(-6847804800) as 'min datetime',
dbo.fn_ConvertToBigDateTime(253402300799) as 'max datetime'
Hope it will help.
You can try converting the millis to days, add the days to beginning of EPOCH, and add the ms part to the date at the end. The problem is that you were trying to convert millis to seconds, which can still be too large number for INT for larger dates.
DATEADD(MILLISECOND,
CAST(myLongDateMs AS BIGINT) % 86400000,
DATEADD(day,
CAST(myLongDateMs AS BIGINT) / 86400000,
'19700101'
)
)
I faced this problem too. In my sql statement, the error occurred when the date time value is null.
My solution is to check whether the date time value is null using "CASE When". Only running the arithmetic when it is not null, and the problem solved.

casting odd smallint time to to datetime format

I'm working with a db (SQL server 2008), and have an interesting issue with times stored in the db.
The DBA who originally set it up was crafty and stored scheduled times as smallints in 12-hour form-- 6:00AM would be represented as 600. I've figured out how to split them into hours and minutes like thus:
select floor(time/100) as hr, right(time, 2) as min from table;
What I want to do is compare these scheduled times to actual times, which are stored in the proper datetime format. Ideally, I would do this with two datetime fields and use datediff() between them, but this would require converting the smallint time into a datetime, which I can't figure out.
Does anyone have suggestions on how to do this?
Thanks in advance.
Can think of two ways to do that. The first is to build a string in the HH:MM format, and cast that to datetime. The second is to convert the smallint format to float with the number of days as unit. The number of days is the internal time representation, so you can cast that to datetime too.
Example code:
declare #i smallint
set #i = 621
-- Cast to a string '6:21', then to a datetime
select cast(CAST(#i / 100 as varchar) + ':' + CAST(#i % 100 as varchar)
as datetime)
-- Convert to number of days, which is the interal datetime format
select cast((#i/100)/24.0 + (#i%100)/(24*60.0) as datetime)
P.S. If you divide an integer by another integer. the result is a third integer: 100 / 24 = 4. If you divide an integer by a float, the result is a float: 100 / 24.0 = 4.16666.
Since you are using SQL Server 2008, you can take advantage of the new Time data type. In order to convert the integer to a time value, we need to assume that the last two digits are minutes. To get the minute portion, divide by 100, take the integer portion and subtract it from the initial value. So in the case of 621 we get:
621 - Floor(621/100)* 100
621 - Floor(6.21)*100
621 - 6*100
621 - 600 = 21 minutes
For the hour portion, we can simply take the integer value after dividing by 100.
Create Table #Test( IntVal smallint not null )
Insert #Test Values( 621 )
Insert #Test Values( 2359 )
Insert #Test Values( 1200 )
Insert #Test Values( 1201 )
Insert #Test Values( 1159 )
Select Z.TimeVal, GetDate(), DateDiff(hh, Z.TimeVal, Cast(GetDate() As Time(0)))
From (
Select Cast(DateAdd(mi
, IntVal - Floor(IntVal/100)*100
, DateAdd(hh, Floor(IntVal/100), 0)
) As Time(0)) As TimeVal
From #Test
) As Z
Part of the trick here is to use DateAdd(hh, Floor(IntVal/100), 0) which does a DateAdd against the zero value for datetime.