.NET以不同的时区和不同的语言环境在SQL中存储DateTime

时间:2008-11-15 18:38:12

标签: c# datetime

在SQL中为不同的时区和不同的语言环境存储DateTime的最佳方法是什么? 有一些关于时区的问题/答案,但没有一个是解决语言环境问题。 DateTime.ToUniversalTime是特定于语言环境的,我需要它独立于语言环境。

例如:

  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 DB上的法国区域设置中保存DateTime,则会出现错误,因为它的日期格式错误。

最好是

的C#代码段
  1. 在特定区域设置中获取日期时间并将其存储在SQL日期时间字段
  2. 检索SQL datetime字段并将其转换为语言环境DateTime
  3. 由于

3 个答案:

答案 0 :(得分:0)

我不清楚你想要实现什么,也许你应该这样做 看看DateTimeOffset课程。这使您可以控制相对于UTC的时间偏移量,并且可以通过这种方式“独立于区域设置”。 您可以将您的时间存储在UTC中的数据库中,然后根据需要进行转换。问题是你想如何转换它。

答案 1 :(得分:0)

我更喜欢所有的时间都是UTC并且出来是用户相关的。这样,应用程序运行的任何服务器位置都变得无关紧要。困难的部分是当时区偏移发生变化时 - 例如,所有不同的时区和夏令时的不同规则等。为此,我使用3.5中的System.TimeZoneInfo类。

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

编辑: 这是我正在研究的项目的片段:

- 用户相对时间 - = TimeZoneInfo.ConvertTimeFromUtc((DateTime)sg.GameTimeUTC,s.User.TimeZoneInfo);

我通过使用TimeZoneInfo的静态ConvertTimeFromUtc获取用户的本地时间,并将我转换的Utc时间以及用户的TimeZoneInfo.Id值(字符串)传递给用户的配置文件。 ConvertTimeFromUtc方法负责处理所有不同时区及其规则的所有丑陋细节。

答案 2 :(得分: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;
        }
    }
}