2016-12-05 28 views
3

我需要在SQL Server中將字符串轉換爲基於.net DateTime類型的不同文化格式的日期時間。我可以使用SQL Server parse函數輕鬆實現大多數文化。如何使用Parse功能控制日曆系統?

SELECT 
PARSE(N'4/22/1996 11:00:00 PM' AS DATETIME USING 'en-US'), 
PARSE(N'6/7/2016' AS DATETIME USING 'en-US'), 
PARSE(N'1/2/2016' AS DATETIME USING 'en-US'), 
PARSE(N'2/1/2016' AS DATETIME USING 'en-US'), 
PARSE(N'1:00:00 AM' AS DATETIME USING 'en-US') 

輸出:

+-------------------------+-------------------------+-------------------------+-------------------------+-------------------------+ 
| 1996-04-22 23:00:00.000 | 2016-06-07 00:00:00.000 | 2016-01-02 00:00:00.000 | 2016-02-01 00:00:00.000 | 2016-12-05 01:00:00.000 | 
+-------------------------+-------------------------+-------------------------+-------------------------+-------------------------+ 

對於文化,都沒有,默認情況下,基於公曆系統我無法弄清楚如何告訴解析funtion使用的日曆系統。

例如,對於ar-SA,默認日曆系統是hijri。我可以爲沿與日期是回曆日期使用parse功能:

SELECT 
PARSE(N'05/12/16 11:00:00 م' AS DATETIME USING 'ar-SA'), 
PARSE(N'02/09/37' AS DATETIME USING 'ar-SA'), 
PARSE(N'22/03/37' AS DATETIME USING 'ar-SA'), 
PARSE(N'22/04/37' AS DATETIME USING 'ar-SA'), 
PARSE(N'01:00:00 ص' AS DATETIME USING 'ar-SA') 

輸出:

+-------------------------+-------------------------+-------------------------+-------------------------+-------------------------+ 
| 1996-04-22 23:00:00.000 | 2016-06-07 00:00:00.000 | 2016-01-02 00:00:00.000 | 2016-02-01 00:00:00.000 | 2016-12-05 01:00:00.000 | 
+-------------------------+-------------------------+-------------------------+-------------------------+-------------------------+ 

不過,我已經在ar-SA格式化的字符串使用Gregorian日曆系統。

當我嘗試使用解析函數

SELECT 
PARSE(N'22/04/1996 11:00:00 م' AS DATETIME USING 'ar-SA'), 
PARSE(N'07/06/2016' AS DATETIME USING 'ar-SA'), 
PARSE(N'02/01/2016' AS DATETIME USING 'ar-SA'), 
PARSE(N'01/02/2016' AS DATETIME USING 'ar-SA'), 
PARSE(N'01:00:00 ص' AS DATETIME USING 'ar-SA') 

將它們轉換我收到以下錯誤:

Error converting string value '22/04/1996 11:00:00 م' into data type datetime using culture 'ar-SA'.

但我需要一種方法來告訴解析字符串日期時間是什麼日曆系統在所以我得到預期的輸出:

+-------------------------+-------------------------+-------------------------+-------------------------+-------------------------+ 
| 1996-04-22 23:00:00.000 | 2016-06-07 00:00:00.000 | 2016-01-02 00:00:00.000 | 2016-02-01 00:00:00.000 | 2016-12-05 01:00:00.000 | 
+-------------------------+-------------------------+-------------------------+-------------------------+-------------------------+ 

有沒有辦法調用解析函數並告訴SQL Server與文化一起使用哪個日曆系統?

更新

轉換不起作用。它不處理阿拉伯am/pm指定,也採用hijri日曆系統。

SELECT 
CONVERT(datetime, N'22/04/1996 11:00:00 م', 131), 
CONVERT(datetime, N'07/06/2016', 131), 
CONVERT(datetime, N'02/01/2016', 131), 
CONVERT(datetime, N'01/02/2016', 131), 
CONVERT(datetime, N'01:00:00 ص', 131) 

輸出:

Conversion failed when converting date and/or time from character string.

當非aribic AM PM名稱仍然使用Hijiri日曆系統

SELECT 
CONVERT(datetime, N'22/04/1996 11:00:00 pm', 131), 
CONVERT(datetime, N'07/06/2016', 131), 
CONVERT(datetime, N'02/01/2016', 131), 
CONVERT(datetime, N'01/02/2016', 131), 
CONVERT(datetime, N'01:00:00 am', 131) 

這導致日期是完全地錯了:

+-------------------------+-------------------------+-------------------------+-------------------------+-------------------------+ 
| 2558-06-10 23:00:00.000 | 2577-12-18 00:00:00.000 | 2577-07-18 00:00:00.000 | 2577-08-16 00:00:00.000 | 1900-01-01 01:00:00.000 | 
+-------------------------+-------------------------+-------------------------+-------------------------+-------------------------+ 
+0

對於那些你們誰不明白[Hijiri日曆]之間的差值(https://en.wikipedia.org/wiki/Islamic_calendar)和[公曆日曆](https://en.wikipedia.org/wiki/Gregorian_calendar)請在回答之前做一些調查。日期不僅以不同的格式表示,而且相同的時間點以不同的值表示。 –

回答

0

我只能假設沒有默認的方式來做到這一點。這是基於在進行日期時間分析時無法找到任何引用控制日曆的材料。

我創建了一個CLR Scalar Value Function來執行始終使用Gregorian日曆的轉換。

用法:

SELECT 
'en-US', 
dbo.ConvertGregorianDateTime(N'4/22/1996 11:00:00 PM', 'en-US'), 
dbo.ConvertGregorianDateTime(N'6/7/2016', 'en-US'), 
dbo.ConvertGregorianDateTime(N'1/2/2016', 'en-US'), 
dbo.ConvertGregorianDateTime(N'2/1/2016', 'en-US'), 
dbo.ConvertGregorianDateTime(N'1:00:00 AM', 'en-US') 
UNION ALL 
SELECT 
'ar-SA', 
dbo.ConvertGregorianDateTime(N'22/04/1996 11:00:00 م', 'ar-SA'), 
dbo.ConvertGregorianDateTime(N'07/06/2016', 'ar-SA'), 
dbo.ConvertGregorianDateTime(N'02/01/2016', 'ar-SA'), 
dbo.ConvertGregorianDateTime(N'01/02/2016', 'ar-SA'), 
dbo.ConvertGregorianDateTime(N'01:00:00 ص', 'ar-SA') 

輸出:

+-------+-------------------------+-------------------------+-------------------------+-------------------------+-------------------------+ 
| en-US | 1996-04-22 23:00:00.000 | 2016-06-07 00:00:00.000 | 2016-01-02 00:00:00.000 | 2016-02-01 00:00:00.000 | 2016-12-07 01:00:00.000 | 
+-------+-------------------------+-------------------------+-------------------------+-------------------------+-------------------------+ 
| ar-SA | 1996-04-22 23:00:00.000 | 2016-06-07 00:00:00.000 | 2016-01-02 00:00:00.000 | 2016-02-01 00:00:00.000 | 2016-12-07 01:00:00.000 | 
+-------+-------------------------+-------------------------+-------------------------+-------------------------+-------------------------+ 

來源:

using Microsoft.SqlServer.Server; 
using System; 
using System.Globalization; 
using System.Linq; 

public static class UserDefinedFunctions 
{ 
    [SqlFunction(DataAccess = DataAccessKind.None, IsDeterministic = true)] 
    public static DateTime ParseGregorianDateTimeString(string dateTimeAsString, string cultureName) 
    { 
     var culture = new CultureInfo(cultureName); 

     culture.DateTimeFormat.Calendar = culture.FindBestGregorianCalendar(); 

     return DateTime.Parse(dateTimeAsString, culture); 
    } 

    private static Calendar FindBestGregorianCalendar(this CultureInfo culture) 
    { 
     var bestGregorianCalendar = (from calendar in culture.OptionalCalendars 
            where calendar is GregorianCalendar 
            orderby (calendar as GregorianCalendar).CalendarType == GregorianCalendarTypes.Localized ? 0 : 1 
            select calendar).FirstOrDefault(); 
     if (bestGregorianCalendar == null) 
     { 
      throw new NotSupportedException(string.Format("The current locale [{0}] is not supported because it doesn't support the Gregorian Calendar System", culture.Name)); 
     } 
     return bestGregorianCalendar; 
    } 
} 

SQL腳本集添加到SQL Server:

CREATE ASSEMBLY [clrFunction] 
FROM 'C:\UserDefinedCLRFunctions\clrFunction.dll' 
WITH PERMISSION_SET = SAFE 

SQL腳本來創建功能:

CREATE FUNCTION ConvertGregorianDateTime(@date as nvarchar(MAX), @locale as nvarchar(10)) 
RETURNS DateTime 
AS external name [clrFunction].UserDefinedFunctions.ConvertGregorianDateTimeString 
0

看到不同風格的參數有沒有辦法來調用解析功能,並告訴SQL服務器的日曆系統與文化一起使用? 不,但您可以將語言更改爲'British'以切換到公曆。

我無法用阿拉伯語am/pm解析格列高利的日期,所以所有這些用am/pm來代替。

例如爲:​​

if exists (select * from tempdb.sys.objects where name like '#Hijri%') begin; drop table #Hijri; end; 
create table #Hijri (strIn nvarchar(32) 
        , amPm nvarchar(32)) 
/* Hijri Format & Gregorian Calendar */ insert into #Hijri (strIn) values (N'22/04/1996 11:00:00 م'),(N'07/06/2016'),(N'02/01/2016'),(N'01/02/2016'),(N'01:00:00 ص') 
/* Hijri Format & Hijri Calendar */ --insert into #Hijri (strIn) values (N'05/12/16 11:00:00 م') ,(N'02/09/37') ,(N'22/03/37') ,(N'22/04/37') ,(N'01:00:00 ص') 
update #Hijri set amPm = replace(replace(strIn,N' م',N' pm'),N' ص',N' am'); 
--set language 'Arabic'; /* implies Hijri Calendar           */ 
--set language 'English'; /* implies Gregorian Calendar & implicitly sets dateformat mdy  */ 
set language 'British'; /* implies Gregorian Calendar & implicitly sets dateformat dmy  */ 
--set dateformat mdy;  /* requires style 103 on convert, overrides language default   */ 
--set dateformat dmy;  /* does not require style 103 on convert, overrides language default */ 

select 
    strIn 
    , amPm 
    , GregorianCalendarDateTime  =convert(datetime2(2),amPm,103) 
    --/* -- requires: set language 'British'; -- or other gregorian calendar culture -- else converts to Hijri Calendar 
    , HijriFormatGregorianCalendar =replace(replace(
            format(convert(datetime2(2),amPm,103), N'dd/MM/yyyy hh:mm:ss tt') 
            ,N' PM',N' م'),N' AM',N' ص') --*/ 
    , HijriFormatHijriCalendar  =format(convert(datetime2(2),amPm,103), N'dd/MM/yyyy hh:mm:ss tt', 'ar-SA') 
    , HijriCalendarDateString  =convert(nvarchar(32),convert(datetime2(2),amPm,103),131) 
    --/* -- requires: set language 'Arabic' or 'British'; or set dateformat dmy; 
    , HijriCalendarDateTime   =convert(datetime2(2),(convert(nvarchar(32),convert(datetime2(2),amPm,103),131)),103) --*/ 
    from #Hijri; 

迴應發表評論:「如果你有一個鏈接,指出日曆系統無法控制的,你可以點我只是想知道?」 數據,datetime,datetime2和datetimeoffset數據類型不存儲變量日曆類型,它們是公曆日曆。當您看到hijri日期時間時,您會看到一種格式應用於8字節日期時間值(或x字節日期時間值)。爲sql server datetime data type

參考鏈接sql server datetime2 data type

即使DateTime in .NET Framework 4.6.2使用公曆。

// This value type represents a date and time. Every DateTime 
// object has a private field (Ticks) of type Int64 that stores the 
// date and time as the number of 100 nanosecond intervals since 
// 12:00 AM January 1, year 1 A.D. in the proleptic Gregorian Calendar. 

.NET Framework 僅使用Calendar參數來解釋年,月和日。

當您使用帶文化參數的parse時,它用於標識表示日期時間值的字符串值的格式。它使用的方式與convert採用確定字符串值的標準(格式)的樣式參數相同。特別是對於阿拉伯文化'ar-SA'和樣式130和131,SQL Server使用Kuwaiti algorithm

+0

我沒有意外切換格式。這些是我需要轉換的日期時間格式。使用格里曆日曆系統在ar-SA語言環境中格式化特定格式。 –

+0

好吧,但這仍然會將這些值轉換爲日期時間格式。你能清理你的問題嗎?所以你只要告訴我們你的實際投入將會是什麼,以及你想要的輸出是什麼,而不是向我們展示你所能做的和不能做的所有事情。 – SqlZim

+0

我已經添加了轉換使用公曆日曆系統創建的ar-SA日期格式時我正在查找的內容。 –