| Author |
Topic |
|
funketekun
Constraint Violating Yak Guru
491 Posts |
Posted - 2007-10-05 : 16:07:31
|
| Trying to write the most effective UDF to convert INT to Datetime.We have a column from a table on AS400 that is a INT type. Some are 4, 5, 6 ,7 digits. I have the 4 digits right. I need to fix it for 5 and 6 digits.ALTER FUNCTION IntegerToDatetime (@int INT) RETURNS DATETIME AS BEGIN DECLARE @IntegerToDatetime intDECLARE @time DATETIMESET @time = '2001-01-01'SET @IntegerToDatetime = CASE WHEN LEN(@int) = 7 THEN '20' + CAST(SUBSTRING(CAST(@int AS CHAR(7)),2,2) AS int) + '-' + CAST(SUBSTRING(CAST(@int AS CHAR(7)),4,2) AS int) + '-' + CAST(SUBSTRING(CAST(@int AS CHAR(7)),6,2) AS int) WHEN LEN(@int) = 6 THEN '19' + CAST(SUBSTRING(CAST(@int AS CHAR(6)),1,2) AS int) + '-' + CAST(SUBSTRING(CAST(@int AS CHAR(6)),3,2) AS int) + '-' + CAST(SUBSTRING(CAST(@int AS CHAR(6)),5,2) AS int) WHEN LEN(@int) = 5 THEN '200' + CAST(SUBSTRING(CAST(@int AS CHAR(5)),1,1) AS int) + '-' + CAST(SUBSTRING(CAST(@int AS CHAR(5)),2,2) AS int) + '-' + CAST(SUBSTRING(CAST(@int AS CHAR(5)),4,2) AS int) WHEN LEN(@int) = 4 THEN cast(@time AS INT)END RETURN (@IntegerToDatetime ) END GOINPUT-------------------------------990831981019RESULT-------------------------------1900-01-02 00:00:00.0001900-05-27 00:00:00.000http://www.sqlserverstudy.com |
|
|
SwePeso
Patron Saint of Lost Yaks
30421 Posts |
Posted - 2007-10-05 : 16:20:39
|
[code]DECLARE @Sample TABLE (i INT)INSERT @SampleSELECT 990831 UNION ALLSELECT 19981019SELECT i, DATEADD(MONTH, 12 * CASE WHEN i / 10000 < 50 THEN i / 10000 + 2000 WHEN i / 10000 <= 99 THEN i / 10000 + 1900 ELSE i / 10000 END - 22801 + (i / 100) % 100, (i % 100) - 1)FROM @Sample[/code] E 12°55'05.25"N 56°04'39.16" |
 |
|
|
funketekun
Constraint Violating Yak Guru
491 Posts |
|
|
SwePeso
Patron Saint of Lost Yaks
30421 Posts |
Posted - 2007-10-05 : 17:07:42
|
"Remember your math from school and read Books Online to learn how datetime related functions work"? E 12°55'05.25"N 56°04'39.16" |
 |
|
|
tkizer
Almighty SQL Goddess
38200 Posts |
Posted - 2007-10-05 : 17:08:58
|
quote: Originally posted by Peso "Remember your math from school and read Books Online to learn how datetime related functions work"?
That's just what I needed to start my weekend on a fun note! Tara KizerMicrosoft MVP for Windows Server System - SQL Serverhttp://weblogs.sqlteam.com/tarad/ |
 |
|
|
funketekun
Constraint Violating Yak Guru
491 Posts |
Posted - 2007-10-05 : 17:16:43
|
| pESO,it doesnt work for 10211221021122 = 2002-11-22, 1 means century 21. we also have 0 which means century 20.http://www.sqlserverstudy.com |
 |
|
|
Lumbago
Norsk Yak Master
3271 Posts |
Posted - 2007-10-05 : 18:54:12
|
Awesome, that last one really made my day --Lumbago"Real programmers don't document, if it was hard to write it should be hard to understand" |
 |
|
|
Kristen
Test
22859 Posts |
Posted - 2007-10-06 : 04:24:34
|
| Doesn't sound very Y2.01K compliant <g>I wonder whether that maths route is the best choice Peso?It will let through illegal dates (20010229 for example), and maybe something that bust the string up into Y,M,D parts, and presents them to SQL Server to convert will at least fail if an illegal date is passed - rather than silently converting it to a different date!Kristen |
 |
|
|
madhivanan
Premature Yak Congratulator
22864 Posts |
Posted - 2007-10-06 : 06:32:32
|
quote: Originally posted by funketekun Peso,It works. What is the name of this formula?http://www.sqlserverstudy.com
Integer to datetime MadhivananFailing to plan is Planning to fail |
 |
|
|
madhivanan
Premature Yak Congratulator
22864 Posts |
Posted - 2007-10-06 : 06:34:45
|
quote: Originally posted by Peso
DECLARE @Sample TABLE (i INT)INSERT @SampleSELECT 990831 UNION ALLSELECT 19981019SELECT i, DATEADD(MONTH, 12 * CASE WHEN i / 10000 < 50 THEN i / 10000 + 2000 WHEN i / 10000 <= 99 THEN i / 10000 + 1900 ELSE i / 10000 END - 22801 + (i / 100) % 100, (i % 100) - 1)FROM @Sample E 12°55'05.25"N 56°04'39.16"
The values 0000000, 888888, etc are also converted to datesMadhivananFailing to plan is Planning to fail |
 |
|
|
funketekun
Constraint Violating Yak Guru
491 Posts |
|
|
jezemine
Master Smack Fu Yak Hacker
2886 Posts |
Posted - 2007-10-07 : 00:30:03
|
here's one way that doesn't allow invalid dates. I'm embarrassed to post it but what the hell.DECLARE @Sample TABLE (i INT)INSERT @Sampleselect 1001231 union all -- leading 1 means from 21st century according to OPselect 1111231 union all -- leading 1 means from 21st century according to OPselect 0990831 union all -- leading 0 means from 20th centuryselect 19981019 -- unambiguousselect convert(datetime, case when i between 1000000 and 1999999 then convert(datetime, '20' + right('000000' + convert(varchar,i),6)) when i between 0 and 999999 then convert(datetime, '19' + right('000000' + convert(varchar,i),6)) else convert(datetime, convert(varchar,i)) end) from @sample -- now try madhi's invalid datesdelete @sampleinsert @sample select 888888 union all select 000000select convert(datetime, case when i between 1000000 and 1999999 then convert(datetime, '20' + right('000000' + convert(varchar,i),6)) when i between 0 and 999999 then convert(datetime, '19' + right('000000' + convert(varchar,i),6)) else convert(datetime, convert(varchar,i)) end) from @sample elsasoft.org |
 |
|
|
SwePeso
Patron Saint of Lost Yaks
30421 Posts |
Posted - 2007-10-07 : 03:23:07
|
So there will be 1) yymmdd2) yyyymmdd3) cyymmddAll these three are mixed in same column?c = century 0 for 1900, 1 for 2000yy = two last digits of the yearmm = monthdd = dayAre there any more combinations that I have missed? E 12°55'05.25"N 56°04'39.16" |
 |
|
|
funketekun
Constraint Violating Yak Guru
491 Posts |
|
|
madhivanan
Premature Yak Congratulator
22864 Posts |
|
|
SwePeso
Patron Saint of Lost Yaks
30421 Posts |
Posted - 2007-10-08 : 04:00:31
|
[code]DECLARE @Sample TABLE (i VARCHAR(8))INSERT @SampleSELECT '1001231' UNION ALLSELECT '0111130' UNION ALLSELECT '19981019' UNION ALLSELECT '20060330' UNION ALLSELECT '980719' UNION ALLSELECT '070228'SELECT i AS OriginalText, DATEADD(MONTH, 12 * theYear - 22801 + theMonth, theDay - 1) AS theDateFROM ( SELECT i, CASE WHEN LEN(i) = 8 THEN CAST(LEFT(i, 4) AS SMALLINT) WHEN LEN(i) = 7 THEN CAST(1900 + 100 * LEFT(i, 1) + SUBSTRING(i, 2, 2) AS SMALLINT) WHEN LEN(i) = 6 AND i <= '491231' THEN CAST('20' + LEFT(i, 2) AS SMALLINT) WHEN LEN(i) = 6 AND i <= '991231' THEN CAST('19' + LEFT(i, 2) AS SMALLINT) ELSE CAST(NULL AS SMALLINT) END AS theYear, CAST(LEFT(RIGHT(i, 4), 2) AS TINYINT) AS theMonth, CAST(RIGHT(i, 2) AS TINYINT) AS theDay FROM @Sample WHERE i NOT LIKE '%[^0-9]%' AND LEN(i) BETWEEN 6 AND 8 ) AS tWHERE theYear IS NOT NULL[/code] E 12°55'05.25"N 56°04'39.16" |
 |
|
|
Kristen
Test
22859 Posts |
Posted - 2007-10-08 : 04:30:40
|
| "Also try to simulate this"That's a very handy function Madhi! |
 |
|
|
madhivanan
Premature Yak Congratulator
22864 Posts |
Posted - 2007-10-08 : 06:04:48
|
quote: Originally posted by Kristen "Also try to simulate this"That's a very handy function Madhi!
Thanks Krsiten. This is exactly how my colleagues expressed MadhivananFailing to plan is Planning to fail |
 |
|
|
|