代码之家  ›  专栏  ›  技术社区  ›  KM.

转换和验证日期字符串的最佳方法

  •  11
  • KM.  · 技术社区  · 15 年前

    在存储过程中,我有一个格式为ddmmyyyy的char(8)变量(该值的质量和有效性未知,超出了我的控制范围)。将值移动到datetime变量中并在无效的datetime中引发错误的最佳方法是什么?

    DECLARE @Source       char(8)
    DECLARE @Destination  datetime
    
    SET @Source='07152009'
    
    --your solution here
    
    
    SELECT @Destination
    

    以下是我能想到的最好方法:

    DECLARE @Source             char(8)
    DECLARE @Temp               varchar(10)
    DECLARE @Destination        datetime
    
    set @Source='07152009'
    SET @Temp=LEFT(@Source,2)+'/'+SUBSTRING(@Source,3,2)+'/'+RIGHT(@Source,4)
    
    IF ISDATE(@Temp)!=1
    BEGIN
        RAISERROR('ERROR, invalid date',16,1)
    END
    SET @Destination=@Temp
    
    SELECT @Source AS Source, @Temp AS  Temp, @Destination AS Destination
    

    编辑 这就是我要说的……

    DECLARE @Source             char(8)
    DECLARE @Destination        datetime
    
    set @Source='07152009'
    BEGIN TRY
        SET @Destination=CONVERT(datetime,RIGHT(@Source,4)        -- YYYY
                                          +LEFT(@Source,2)        -- MM
                                          +SUBSTRING(@Source,3,2) -- DD
                                 )
    END TRY
    BEGIN CATCH
        PRINT 'ERROR!!!' --I'll add a little more logic here and abort processing
    END CATCH
    
    SELECT @Source AS Source, @Destination AS Destination
    
    2 回复  |  直到 14 年前
        1
  •  12
  •   marc_s    15 年前

    首先,由于您使用的是SQL Server 2005,因此应该将 可以 失败为 BEGIN TRY.....END TRY BEGIN CATCH....END CATCH 块-T-SQL的Try/Catch块!

    第二,对于所有的日期操纵,我会 总是 使用 ISO-8601 format 无论在SQL Server中设置了什么当前日期格式,它都可以工作。

    ISO-8601格式为 YYYYMMDD 只是约会,或者 YYYY-MM-DDTHH:MM:SS 为了日期和时间-所以我把你的代码写为:

    BEGIN TRY
      SET @Source='07152009'
      SET @Temp = RIGHT(@Source, 4) +             -- YYYY
                  LEFT(@Source, 2) +              -- MM
                  SUBSTRING(@Source, 3, 2)        -- DD
    
      IF ISDATE(@Temp)!=1
      BEGIN
          RAISERROR('ERROR, invalid date',16,1)
      END
    
      SET @Destination = CAST(@Temp AS DATETIME)
    END TRY
    BEGIN CATCH
          -- handle error if something bombs out
    END CATCH
    

    不要依赖正在设置的任何特定日期格式!!把你的代码发给我,我会在瑞士-德国的系统上试用它-我几乎保证如果你盲目地假设“en-us”和“mm/dd/yyyy”,它会坏的-它是 这个星球上到处都是相同的环境。

    不幸的是,SQL Server处理日期的能力相当弱——也许这可能是一个扩展点,在该扩展点使用SQL Server内部的CLR程序集将很有意义,可以利用.NET中更丰富的日期处理功能吗??

    马克

    PS:似乎我知道的ISO-8601格式YYYY-MM-DD在SQL Server中并不总是有效,这与在线书籍所宣扬的相反。请改用YYYYMMDD或YYYY-MM-DDTHH:mm:ss。
    谢谢,GBN!

        2
  •  6
  •   Andriy M    14 年前

    您可以使用设置日期格式来保证日期-月-年订单。 这意味着ISDATE将把“15-07-2009”解析为2009年7月15日。

    否则,考虑到外部限制,您的方法就足够好了…但是您也可以重新排序为ANSI/ISO。

    在Marc_的回答之后:“set dateformat dmy”适用于大多数欧洲设置…

    好啊:

    SET LANGUAGE british
    SELECT ISDATE('2009-07-15') --this is ansi says marc_s. It gives "zero"
    SELECT ISDATE('2009-07-15T11:22:33') --this really is ANSI and gives true
    
    
    SET LANGUAGE german
    SELECT ISDATE('2009-07-15') --false
    SELECT ISDATE('2009-07-15T11:22:33') --true