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

时间:2012-08-12 06:55:52

标签: c# datetime timezone

用户在单独的文本框中输入日期和时间。然后我将日期和时间合并到一个日期时间。我需要将此日期时间转换为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);

这导致了一个例外:

The conversion could not be completed because the supplied DateTime did not have the Kind property set correctly. For example, when the Kind property is DateTimeKind.Local, the source time zone must be TimeZoneInfo.Local

然后我尝试设置Kind属性:

DateTime.SpecifyKind(combinedDateTime, DateTimeKind.Local);

这不起作用,所以我尝试了:

DateTime.SpecifyKind(combinedDateTime, DateTimeKind.Unspecified);

这也不起作用。任何人都可以解释我需要做什么吗?我甚至会以正确的方式解决这个问题吗?我应该使用DateTimeOffset吗?

2 个答案:

答案 0 :(得分:7)

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

combinedDateTime = DateTime.SpecifyKind(combinedDateTime,
                                        DateTimeKind.Unspecified);

就我个人而言,我建议使用Noda Time,这使我在相当偏见的观点中更加清晰(我是主要作者)。你最终会得到这个代码:

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更改,本地值可能在时区中无效或不明确。

答案 1 :(得分:1)

您也可以尝试

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