在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#代码段由于
答案 0 :(得分:0)
我不清楚你想要实现什么,也许你应该这样做 看看DateTimeOffset课程。这使您可以控制相对于UTC的时间偏移量,并且可以通过这种方式“独立于区域设置”。 您可以将您的时间存储在UTC中的数据库中,然后根据需要进行转换。问题是你想如何转换它。
答案 1 :(得分:0)
我更喜欢所有的时间都是UTC并且出来是用户相关的。这样,应用程序运行的任何服务器位置都变得无关紧要。困难的部分是当时区偏移发生变化时 - 例如,所有不同的时区和夏令时的不同规则等。为此,我使用3.5中的System.TimeZoneInfo类。
编辑: 这是我正在研究的项目的片段:
- 用户相对时间 - = 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;
}
}
}