C# 将用户输入的日期时间转换为UTC

C# 将用户输入的日期时间转换为UTC,c#,datetime,timezone,C#,Datetime,Timezone,用户在单独的文本框中输入日期和时间。然后,我将日期和时间合并为日期时间。我需要将此日期时间转换为UTC以将其保存在数据库中。我将用户的时区id保存在数据库中(他们在注册时选择它)。首先,我尝试了以下方法: string userTimeZoneID = "sometimezone"; // Retrieved from database TimeZoneInfo userTimeZone = TimeZoneInfo.FindSystemTimeZoneById(userTimeZoneID);

用户在单独的文本框中输入日期和时间。然后,我将日期和时间合并为日期时间。我需要将此日期时间转换为UTC以将其保存在数据库中。我将用户的时区id保存在数据库中(他们在注册时选择它)。首先,我尝试了以下方法:

string userTimeZoneID = "sometimezone"; // Retrieved from database
TimeZoneInfo userTimeZone = TimeZoneInfo.FindSystemTimeZoneById(userTimeZoneID);

DateTime dateOnly = someDate;
DateTime timeOnly = someTime;
DateTime combinedDateTime = dateOnly.Add(timeOnly.TimeOfDay);
DateTime convertedTime = TimeZoneInfo.ConvertTimeToUtc(combinedDateTime, userTimeZone);
这导致了一个例外:

无法完成转换,因为提供的DateTime没有正确设置Kind属性。例如,当种类属性为DateTimeKind.Local时,源时区必须为TimeZoneInfo.Local

然后,我尝试将Kind属性设置为:

DateTime.SpecifyKind(combinedDateTime, DateTimeKind.Local);
这不起作用,所以我试着:

DateTime.SpecifyKind(combinedDateTime, DateTimeKind.Unspecified);

这也没用。有人能解释一下我需要做什么吗?我这样做对吗?我应该使用DateTimeOffset吗?

就像
DateTime
上的所有其他方法一样,
SpecifyKind
不会更改现有值-它会返回一个新值。你需要:

combinedDateTime = DateTime.SpecifyKind(combinedDateTime,
                                        DateTimeKind.Unspecified);
就我个人而言,我建议使用它,以我的偏见观点(我是主要作者),它会使这类事情变得更加清晰。您将得到以下代码:

DateTimeZone zone = ...;
LocalDate date = ...;
LocalTime time = ...;
LocalDateTime combined = date + time;
ZonedDateTime zoned = combined.InZoneLeniently(zone);
// You can now get the "Instant", or convert to UTC, or whatever...

“宽松”部分是因为当您将本地时间转换为特定区域时,由于DST更改,本地值可能在时区中无效或不明确。

您也可以尝试此操作

var combinedLocalTime = new DateTime((dateOnly + timeOnly.TimeOfDay).Ticks,DateTimeKind.Local);
var utcTime = combinedLocalTime.ToUniversalTime();

@Shai:显然不是重复的,因为问题是:“我必须在.NET framework 3.0中使用,所以不能使用TimeZoneInfo对象。”@JonSkeet Ahhh没有看到这一点,但可能会给OP一个线索……谢谢Jon!真不敢相信这么简单!我将查看野田佳彦时间,因为它看起来使用起来更简单@HTX9:Goodo-您可能会发现,最初它实际上感觉更复杂,因为它迫使您实际计算出您拥有的数据类型(本地、日期、时间、日期/时间)、如何处理歧义等。这些都是您应该考虑的事情,但.NET API使您更难发现它们。不管怎样,这就是理论:)