如何将日期字符串解析为NodaTime对象?

6

我是NodaTime的新手,希望在我的应用程序中实现它。

我该如何将日期字符串解析为NodaTime对象?

这是我目前拥有的:

var dateInput = "06/11/2015";
var pattern = InstantPattern.CreateWithInvariantCulture("dd/MM/yyyy");
var parseResult = pattern.Parse(dateInput);
var localDate = parseResult.Value;
DateTimeZone tzNZ = DateTimeZoneProviders.Tzdb["Asia/Hong_Kong"];
ZonedDateTime result = localDate.InZone(tzNZ);

我的localDate变量现在是2015-11-06T00:00:00Z(根据我所读的ISO格式,最后一部分中有Z表示它是UTC)

我的result变量现在是2015-11-06T13:00:00 NZ (+13)

但我不确定我是否走对了路。

以下是我真正想要的:

  1. dateInput(日期字符串)转换为NodaTime对象,格式为dd/MM/yyyy
  2. 然后将其作为UTC,转换为long数据类型,然后保存到数据库中
  3. 然后尝试检索保存的数据,使用特定时区。比如说Asia/Hong_Kong

这是可能的吗?

编辑

var dateInput = "06/11/2015";
var pattern = LocalDatePattern.CreateWithInvariantCulture("dd/MM/yyyy");
LocalDate parseResult = pattern.Parse(dateInput).Value;
DateTimeZone tzHK = DateTimeZoneProviders.Tzdb["Asia/Hong_Kong"];
LocalTime time = GetTimeOfDay();
LocalDateTime localDateTime = parseResult + time;

// change it to UTC then convert it to 
// long data type then save it to the database

// methods
private LocalTime GetTimeOfDay()
{
  var instant = SystemClock.Instance.Now;
  var tz = DateTimeZoneProviders.Tzdb["Asia/Hong_Kong"];

  return instant.InZone(tz).TimeOfDay;
}

我有这个片段以及这个场景,用户只能输入日期,例如06/11/2015,然后将其保存到数据库中,在查看时需要使用当前时间(用户的当前时间)。我将其转换为“long”的原因是因为我正在使用Entity Framework。
这样做是否可行?

关于您的编辑问题 - 在这种情况下,为什么要让他们输入日期?这听起来像是您正在使用当前日期和时间对订单进行时间戳处理。 - Matt Johnson-Pint
@MattJohnson 这只是我想出来的一个想法,但我现在意识到它没有任何意义。我认为我需要将其删除。 - Boy Pasmo
如果你只是需要时间戳,那么上面的内容都不适用了,因为你可以直接使用SystemClock.Instance.Now来获取当前基于UTC的Instant。或者在数据库中使用DateTime.UtcNow或类似的函数,这样你就完全不需要使用Noda Time了。 - Matt Johnson-Pint
1个回答

5
我会从一个稍微不同的角度来回答。你说你正在转换为long,因为你正在使用Entity Framework。那可能并不是必要的。
听起来你只是想往返一个日历日期。如果没有特定时间参与(如午夜或一天的开始),并且您希望所有用户无论身处哪个时区都能看到相同的年月和日,则最好(在我看来)在整个过程中保持这些术语。
有些人会反对这种做法,常见的最佳做法是“始终存储为UTC”,但这个建议在两种常见情况下不适用:
1. “我有一个本地日期和时间,但它们在未来,我将它们用于调度目的。” 2. “我只是处理一个没有任何时刻的日历日期,它可能是过去、现在或将来,但它是以人类为中心的公民日期,而不是一个独特的时间点。”
你似乎处于第二种情况。所以:
1. 在数据库中使用仅日期类型,例如SQL Server、PostgreSQL、MySQL、Oracle和大多数其他关系型数据库中提供的DATE类型。 2. 在Noda Time中使用LocalDate类型。不要尝试将其转换为InstantLocalDateTimeZonedDateTimelong。 3. 使用DateTime类型(带有.Kind == DateTimeKind.Unspecified),作为数据库和你的LocalDate属性之间的中间件。这通常是使用“伙伴属性”模式完成的,如在这个答案中所示。

请注意,我的回答中有几个假设。如果您实际上并不只是尝试往返一个日历日期,请告诉我,我会删除或修改我的回答。谢谢。 - Matt Johnson-Pint
哦,所以我可以使用您的方法来使用DATE并仅在数据库中存储DATE,而不必担心“始终存储UTC”的规则?我一直认为并根据我所读的,您应该始终存储UTC。我从未想过有例外。我真的不确定“round-trip a calendar date”是什么意思。 - Boy Pasmo
是的,这就是我的意思。 "round-trip" 的概念是您可以获得保存或传输的确切值。它开始作为字符串“2015-11-01”,保存到数据库中为2015-11-01,并且可以使用相同的值从数据库加载。 (不进行 round trip 的内容可能类似于设置 DateTimeKind.Utc,它不会保存到数据库中,因此在返回时将是 DateTimeKind.Unspecified。) - Matt Johnson-Pint
1
“始终存储UTC”是短视的,因为并非所有日期/时间值都是精确的时间戳。如果您要存储特定的时间戳(例如2015-11-01T00:00:00-07:00),则可以将其转换为UTC进行存储,如2015-11-01T07:00:00Z,然后可以轻松地从任何时区进行投影。但是,当您只有一个日期时,那就不完全是时间戳了。 - Matt Johnson-Pint
为什么要使用 DateTimeKind.UnspecifiedDateTimeKind.Local呢?这真的很重要吗?我同意总是存储为UTC不是一个好主意。如果请求包含偏移量,您将丢失信息。 - onefootswill

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