将UTC日期时间转换为DateTimeOffset

36

我需要将UTC日期字符串转换为DateTimeOffsets

这必须适用于与计算机时区不同的时区。 例如,当前计算机时区为+02:00,但我想要创建一个偏移量为-4:00的DateTimeOffset。

我已经在stackoverflow上阅读了很多问题,但没有解决我的问题。

这就是我需要做的:

输入:"2012-11-20T00:00:00Z"

输出:具有以下属性的DateTimeOffset:

  • UtcDateTime: 2012-11-20 00:00
  • 定义时区的正确UTC偏移量(在此示例中为01:00)
  • LocalDateTime: 2012-11-20 01:00 (= UtcDateTime + Offset)

当然,必须考虑夏令时。

编辑: 为使事情更加清晰,请尝试完成以下代码片段:

DateTimeOffset result;
const string dateString = "2012-11-20T00:00:00Z";
var timezone = TimeZoneInfo.FindSystemTimeZoneById("W. Europe Standard Time"); //this timezone has an offset of +01:00:00 on this date

//do conversion here

Assert.AreEqual(result.Offset, new TimeSpan(1, 0, 0));  //the correct utc offset, in this case +01:00:00
Assert.AreEqual(result.UtcDateTime, new DateTime(2012, 11, 20, 0, 0, 0)); //equals the original date
Assert.AreEqual(result.LocalDateTime, new DateTime(2012, 11, 20, 1, 0, 0));
4个回答

22

这是您正在寻找的解决方案:

const string dateString = "2012-11-20T00:00:00Z";
TimeZoneInfo timezone = TimeZoneInfo.FindSystemTimeZoneById("W. Europe Standard Time"); //this timezone has an offset of +01:00:00 on this date

DateTimeOffset utc = DateTimeOffset.Parse(dateString);
DateTimeOffset result = TimeZoneInfo.ConvertTime(utc, timezone);
        
Assert.AreEqual(result.Offset, new TimeSpan(1, 0, 0));  //the correct utc offset, in this case +01:00:00
Assert.AreEqual(result.UtcDateTime, new DateTime(2012, 11, 20, 0, 0, 0)); //equals the original date
Assert.AreEqual(result.DateTime, new DateTime(2012, 11, 20, 1, 0, 0));

请注意,您错误地测试了.LocalDateTime属性 - 这个属性会始终将结果转换为计算机的本地时区。您只需要使用.DateTime属性即可。


2
@BojidarStanchev - var 并没有问题,但我同意显式类型声明可以使示例更清晰。我已经相应地编辑了答案。请记住,原始答案是8年前发布的。此外,您也可以提出编辑建议,而不是抱怨。 - Matt Johnson-Pint
2
抱怨同样有效,而且更省力。 - Bojidar Stanchev

8
这是您想要的吗:
[Test]
public void ParseUtcDateTimeTest()
{
    DateTime dateTime = DateTime.Parse("2012-11-20T00:00:00Z");
    Assert.AreEqual(new DateTime(2012, 11, 20, 01, 00, 00), dateTime);
    DateTimeOffset dateTimeOffset = new DateTimeOffset(dateTime);
    Assert.AreEqual(new TimeSpan(0, 1, 0, 0), dateTimeOffset.Offset);
}
  • 请注意,我的断言在瑞典(CET)是有效的
  • DateTime.Parse() 有一些重载方法

这对您的转换有用吗:

[Test]
public void ConvertTimeTest()
{
    DateTime dateTime = DateTime.Parse("2012-11-20T00:00:00Z");
    TimeZoneInfo cstZone = TimeZoneInfo.FindSystemTimeZoneById("Central Standard     Time");
    DateTime convertedTime = TimeZoneInfo.ConvertTime(dateTime, cstZone);
    Assert.AreEqual(new DateTime(2012, 11, 19, 18, 00, 00), convertedTime);
    TimeSpan baseUtcOffset = cstZone.BaseUtcOffset;
    Assert.AreEqual(new TimeSpan(0, -6, 0, 0), baseUtcOffset);
}

如果我想使用另一个时区而不是当前时区,这将无法工作。 - Fabian
@Fabian 我更新了我的回答,希望能有所帮助。 - Johan Larsson
1
我不确定这怎么能帮到我。转换DateTime很好,但我如何获得DateTimeOffset? - Fabian

0
    public static DateTimeOffset ToDatetimeOffsetFromUtc(this DateTime date) =>
        new DateTimeOffset(DateTime.SpecifyKind(date, DateTimeKind.Utc));

试试这个扩展

-1
const String dateString = "2012-11-20T00:00:00Z"; 
var offsetDate = DateTimeOffset.Parse(dateString); 
var offsetDate2 = DateTime.Parse(dateString);

输出为

offsetDate  {20-11-2012 0:00:00 +00:00}    System.DateTimeOffset
offsetDate2 {20-11-2012 1:00:00}           System.DateTime

如果我想使用另一个时区而不是当前时区,这将无法工作。 - Fabian
添加第二个参数,CultureInfo。这里有一个列表http://sharpertutorials.com/list-of-culture-codes/。例如:var fmt = new CultureInfo("en-AU").DateTimeFormat; - VRC
我尝试过这个,但无论我使用哪种CultureInfo,DateTimeOffset始终具有00:00:00的偏移量,这不是我想要的! - Fabian

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接