使用Noda Time c#时获得无效结果

时间:2014-06-10 12:48:11

标签: c# nodatime

假设即时变量包含“4/8/2014 11:09:24 AM”,当我将此值传递给此方法时,它给出了输出“4/8/2014 12:09:24 PM”我检查了一些时区计算器加上oracle我应该得到“4/8/2014 04:09:24 PM”或“4/8/2014 16:09:24 PM”,具体取决于小时格式。为什么没有转换成适当的时间格式?

public static string ConvertDateTimeToUserTimeZone()
{
    DateTime dt = DateTime.Parse("4/8/2014 11:09:24 AM");
    Instant now = Instant.FromDateTimeUtc(DateTime.SpecifyKind(dt,DateTimeKind.Utc));
    DateTimeZone dtZone = DateTimeZoneProviders.Tzdb["Europe/London"];
    ZonedDateTime zdt = now.InZone(dtZone);
    return zdt.ToDateTimeOffset().ToString("G");
}

2 个答案:

答案 0 :(得分:3)

阅读您的评论,您似乎想要执行以下操作:

  • 解析输入字符串
  • 将其分配到美国东部时区("America/New_York"
  • 将其转换为英国的时区("Europe/London"
  • 将其格式化为一般格式的字符串

我将使用Noda Time显示所有这些步骤,而不是混合使用非Noda机制。

var generalPattern = LocalDateTimePattern.CreateWithCurrentCulture("G");

string inputString = "4/8/2014 11:09:24 AM";
string sourceTimeZone = "America/New_York";
string targetTimeZone = "Europe/London";

LocalDateTime ldt1 = generalPattern.Parse(inputString).Value;
DateTimeZone tz1 = DateTimeZoneProviders.Tzdb[sourceTimeZone];
ZonedDateTime zdt1 = ldt1.InZoneLeniently(tz1);

DateTimeZone tz2 = DateTimeZoneProviders.Tzdb[targetTimeZone];
ZonedDateTime zdt2 = zdt1.WithZone(tz2);
LocalDateTime ldt2 = zdt2.LocalDateTime;

string output = generalPattern.Format(ldt2);

请注意,我在设置模式时使用了CreateWithCurrentCulture。这假设您的意思是使用当前文化对运行代码的机器的任何内容。如果情况并非如此,那么您应该设置一个特定的文化。当您意识到美国用户将使用M / D / Y格式时,这一点很重要,而英国用户将使用D / M / Y格式。无论时区如何,这都适用于两个日期。 (换句话说,4/8/2014可以是4月8日,也可以是8月4日。

另请注意,我在应用源时区时使用了InZoneLeniently。当由于DST transitions导致模糊和无效的输入值时,这具有宽松的行为。如果您想要不同的行为,则可以使用InZoneStrictly,或使用InZone并提供自己的算法。

最后,应该注意的是,我从您的评论中推断出您是从美国东部时区采购这些产品,这些时区可能是美国东部时间或美国东部时间,具体取决于一年中的什么时间。如果您实际上意味着值总是 EDT,即使EST是常态,那么您将执行以下操作:

DateTimeZone tz1 = DateTimeZone.ForOffset(Offset.FromHours(-4));

答案 1 :(得分:2)

从方法中获得的值实际上是正确的。

让我们使用LINQPad

分解它
void Main()
{
    var t = new DateTime(2014, 8, 4, 11, 09, 24, DateTimeKind.Utc);
    var i = Instant.FromDateTimeUtc(t);
    var s = ConvertDateTimeToUserTimeZone(i);
    s.Dump("User time zone value");
}

public static string ConvertDateTimeToUserTimeZone(Instant now)
{
    DateTimeZone dtZone = DateTimeZoneProviders.Tzdb["Europe/London"];
    dtZone.GetUtcOffset(now).Dump("TZ at instant");
    ZonedDateTime zdt = now.InZone(dtZone);
    return zdt.ToDateTimeOffset().ToString("G");
}

输出:

TZ at instant 
+01 

User time zone value 
04.08.2014 12:09:24 

那个时刻的时区因此是UTC + 1,这意味着你给代码的值会给你正确的值,12:09。

要获得16:09,您需要UTC + 5,而欧洲/伦敦从未达到过该值。

所以12:09:24是正确的,你应该是16:09:24的假设是错误的。

您需要返回用于获取"正确"的代码和/或网站。价值,你的困惑的根源在那里,而不是在这个代码中。