2008-11-15 32 views
1

什麼是存儲日期時間在SQL的不同的時區和不同的語言環境的最佳途徑
有幾個問題/回答有關時區,但都不是解決區域問題。 DateTime.ToUniversalTime是特定於語言環境的,我需要它獨立於語言環境。.NET存儲日期時間在SQL中不同的時區和不同的區域

例如:

DateTime.Now.ToUniversalTime.ToString() 
     In US locale returns something like: 11/23/2008 8:20:00 
     In France locale returns 23/11/2008 8:20:00 

Notice that day/month are inverted 

如果保存日期時間,而在法國區域設置在美國SQL數據庫 - 你得到一個錯誤,因爲這是一個錯誤的日期格式。

最佳將是一個C#代碼片段

  1. 在一個特定的區域獲取一個DateTime並將其存儲在SQL日期時間字段
  2. 檢索到的SQL日期時間字段並將其轉換爲一個區域設置日期時間

感謝

+0

究竟是什麼意思,「獨立於區域的轉換爲UTC」,時間轉換固有地依賴於您轉換的時區。你想擺脫考慮的夏令時? – axk 2008-11-15 18:57:21

回答

0

這是我不清楚你想達到什麼,也許你應該 看看DateTimeOffsetç姑娘。這使您可以控制相對於UTC的時間偏移,並且您可以通過這種方式實現「區域獨立」。 您可以將時間以UTC存儲在數據庫中,然後根據需要進行轉換。問題是你想如何轉換它。

+0

我在這個問題上增加了更多信息 - 我希望它更清晰.. – LeJeune 2008-11-15 20:32:21

0

我更喜歡所有的時間都是UTC並且出來是用戶相對的。這樣,應用程序運行的任何服務器位置都變得無關緊要。最難的部分是時區偏移量的變化 - 例如,所有不同的時區和夏令時的不同規則等。爲此,我使用3.5中的System.TimeZoneInfo類。

http://csharpfeeds.com/post/5336/Exploring_Windows_Time_Zones_with_System.TimeZoneInfo_Josh_Free.aspx

編輯: 這裏有一個片段從項目現在我的工作:

- 使用者相對時間 - = TimeZoneInfo.ConvertTimeFromUtc((日期時間)sg.GameTimeUTC, s.User.TimeZoneInfo);

我通過使用TimeZoneInfo的靜態ConvertTimeFromUtc並傳遞它從我轉換的Utc時間以及用戶的配置文件中存儲的用戶的TimeZoneInfo.Id值(字符串)來獲取用戶的本地時間。 ConvertTimeFromUtc方法負責處理所有不同時區及其規則的所有醜陋的細節。

0

如果您只需在數據庫中以UTC保存DateTime,這應該不成問題,以下內容應該適用於IMO。

namespace MyNamespace 
{ 
    using System; 
    using System.Collections.Generic; 
    using System.Data; 
    using System.Data.Common; 
    using System.Data.SqlClient; 

    using System.Globalization; 

    using System.Threading; 

    public sealed class MyProgram 
    { 
     private DbConnectionStringBuilder connectionStringBuilder; 

     public static void Main(string[] args) 
     { 
      DbConnectionStringBuilder connectionStringBuilder = new SqlConnectionStringBuilder(args[0]); 
      MyProgram myProgram = new MyProgram(connectionStringBuilder); 
      myProgram.Run(); 
     } 

     public MyProgram(DbConnectionStringBuilder connectionStringBuilder) 
     { 
      if (null == connectionStringBuilder) 
      { 
       throw new ArgumentNullException("connectionStringBuilder"); 
      } 

      this.connectionStringBuilder = connectionStringBuilder; 
     } 

     public void Run() 
     { 
      IList<Guid> guids = new List<Guid>(2); 
      guids.Add(this.Create(DateTime.Now)); 
      Thread.Sleep(new TimeSpan(0, 0, 5)); // I just want to assure there is a different time in the next row. :) 
      guids.Add(this.Create(DateTime.UtcNow)); 

      foreach(Guid guid in guids) 
      { 
       Console.WriteLine(this.Retrieve(guid)); 
      } 
     } 

     private Guid Create(DateTime dateTime) 
     { 
      Guid result = Guid.Empty; 



      if (dateTime.Kind == DateTimeKind.Unspecified) 

      { 

       throw new ArgumentException("I cannot work with unspecified DateTimeKinds.", "dateTime"); 

      } 

      else if (dateTime.Kind == DateTimeKind.Local) 

      { 

       dateTime = dateTime.ToUniversalTime(); 

      } 

      using (IDbConnection connection = new SqlConnection(this.connectionStringBuilder.ConnectionString)) 
      { 
       using (IDbCommand command = connection.CreateCommand()) 
       { 

        command.CommandText = "INSERT INTO MyTable (MyUtcDate) OUTPUT INSERTED.Id VALUES (@DateTime)"; 

        IDataParameter parameter = command.CreateParameter(); 
        parameter.ParameterName = "DateTime"; 
        parameter.Value = dateTime; 
        command.Parameters.Add(parameter); 

        command.Connection.Open(); 

        result = (Guid)command.ExecuteScalar(); 
       } 
      } 

      return result; 
     } 

     private string Retrieve(Guid id) 
     { 

      string result = string.Empty; 

      using (IDbConnection connection = new SqlConnection(this.connectionStringBuilder.ConnectionString)) 
      { 
       using (IDbCommand command = connection.CreateCommand()) 
       { 
        command.CommandText = "SELECT MyUtcDate FROM MyTable WHERE Id = @Id"; 

        IDataParameter parameter = command.CreateParameter(); 
        parameter.ParameterName = "Id"; 
        parameter.Value = id; 
        command.Parameters.Add(parameter); 

        command.Connection.Open(); 
        using (IDataReader dataReader = command.ExecuteReader(CommandBehavior.SingleRow)) 
        { 
         if (dataReader.Read()) 
         { 
          DateTime myDate = DateTime.SpecifyKind(dataReader.GetDateTime(dataReader.GetOrdinal("myUtcDate")), DateTimeKind.Utc); 

          result = string.Format(CultureInfo.CurrentCulture, "{0}: {1}, {2}: {3}", TimeZoneInfo.Utc.StandardName, myDate, TimeZoneInfo.Local.StandardName, myDate.ToLocalTime()); 
         } 
        } 
       } 
      } 



      return result; 
     } 
    } 
} 
相關問題