简体   繁体   English

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

[英]Getting invalid result when using Noda Time c#

Assume Instant variable contains "4/8/2014 11:09:24 AM" when i pass this value to this method it gives me an output "4/8/2014 12:09:24 PM" i checked in some time zone calcluator plus in oracle i should be getting "4/8/2014 04:09:24 PM" or "4/8/2014 16:09:24 PM" depending on hour format. 假设即时变量包含“ 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”。 why is it not converting into proper time format? 为什么不转换为正确的时间格式?

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");
}

Reading through your comments, it would appear that you'd like to do the following: 阅读您的评论后,您似乎想执行以下操作:

  • Parse the input string 解析输入字符串
  • Assign it to the the US Eastern time zone ( "America/New_York" ) 将其分配给美国东部时区( "America/New_York"
  • Convert it to the time zone for the UK ( "Europe/London" ) 将其转换为英国的时区( "Europe/London"
  • Format it as a string in the general format 将其格式化为通用格式的字符串

I will show using Noda Time for all of these steps, rather than mixing in non-Noda mechanisms. 我将展示在所有这些步骤中使用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);

Notice that I used CreateWithCurrentCulture when setting up the pattern. 请注意,设置模式时我使用了CreateWithCurrentCulture This assumes you mean to use whatever the current culture is for the machine the code is running on. 假定您的意思是对运行代码的计算机使用当前的区域性。 If that's not the case, then you should set a specific culture instead. 如果不是这种情况,则应该设置特定的区域性。 This is important when you realize that users in the US will use M/D/Y formatting, while users in the UK will use D/M/Y formatting. 当您意识到美国用户将使用M / D / Y格式,而英国用户将使用D / M / Y格式时,这一点很重要。 This applies to both dates regardless of time zone. 这适用于两个日期,与时区无关。 (In other words, 4/8/2014 could be April 8th, or August 4th). (换句话说, 4/8/2014 4月8日可能是4月8日或8月4日)。

Also notice that I used InZoneLeniently when applying the source time zone. 还要注意,在应用源时区时我使用了InZoneLeniently This has lenient behavior when it comes to ambiguous and invalid input values due to DST transitions . 当由于DST转换而导致模棱两可和无效的输入值时,这具有宽松的行为。 If you want different behavior, then you might instead use InZoneStrictly , or use InZone and provide your own algorithm. 如果您想要不同的行为,则可以改用InZoneStrictly或使用InZone并提供自己的算法。

And finally, it should be noted that I inferred from your comments that you were sourcing these from the US Eastern time zone, which would be either EDT or EST depending on what time of year it is. 最后,应该指出的是,我从您的评论中推断出,您是从美国东部时区(美国东部时区或美国东部时区)采购这些信息的,具体取决于每年的时间。 If you actually meant that the values were always EDT, even when EST is the norm, then you would do the following: 如果实际上是说值始终是 EDT,即使以EST为标准,那么您应该执行以下操作:

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

The value you got back from the method is in fact correct. 从该方法获得的值实际上是正确的。

Let's break it down using LINQPad : 让我们使用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");
}

Output: 输出:

TZ at instant 
+01 

User time zone value 
04.08.2014 12:09:24 

The time zone at the point of that instant is thus UTC+1, which means that the value you gave the code gives you the correct value back, 12:09. 因此,该时刻的时区为UTC + 1,这意味着您为代码提供的值将为您提供正确的值12:09。

To get 16:09, you would need UTC+5, and Europe/London has never been that value. 要获得16:09,您将需要UTC + 5,而欧洲/伦敦从未如此。

So 12:09:24 is correct, your assumptions that it should be 16:09:24 is wrong. 所以12:09:24是正确的,您认为应该为16:09:24是错误的。

You need to go back to the code and/or sites you used to get the "correct" value, the source of your confusion is there, not in this code. 您需要返回到用于获得“正确”值的代码和/或站点,您的困惑之源就在这里,而不是在此代码中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM