为什么LocalDateTime实际上不是本地日期和时间?

时间:2015-03-22 00:20:44

标签: .net nodatime

作为一名软件架构师,我真的很想使用NodaTime,但它的概念是“本地”和#39;本地'使我们的代码非常难以使用(它正在驱使我和我的团队坚果)! documentation引用" local"和"全球"时代陈述如下:

  

关键的区别在于世界各地的人们都会同意   一个全局值,但他们可能都看到不同   本地值为相同的全局值,由于时区

这句话通过使用本地时间的定义来定义全球时间的含义。因此,在我们能够理解全球时间之前,我们必须首先了解当地时间的含义。

Google(以及其他许多类似的词典)定义了" Local Time"为:

  

计算在特定区域或时区的时间。

     
      
  • 特定地点的时间,根据太阳在那个地方经过子午线的过程来衡量,定义为中午。
  •   

因此,本地时间是由时区定义(或绑定)的特定时间 - 得到它。现在我们完全理解全球时间意味着什么;好的,下一句:

  

本地值在Noda Time中具有关联的时区;

等待!什么......?!文档刚刚通过使用普遍接受的本地时间定义( 与时区相关联)来定义全球时间,现在他们决定完全否定它的意义,如果这是真的,全球时间现在意味着什么?恕我直言,绝对没有。

文档继续陈述......

  

特别是只是"日期和时间固定在运行代码的计算机的本地时间

我对此声明有两个问题:

  1. 文档无法使用本地时间的通用定义' 尝试来描述它不是什么。这就像说X is equal to (NOT X) is true
  2. 由于使用计算机的日期和时间完全定义了"本地时间",那我该怎么称呼当地时间?
  3. 我投票表示我们使用的定义比“本地”更好,“' Raw'”这个词怎么样?这意味着:

      

    处于或接近自然状态:未加工或纯化。

    嗯....

      

    [原始]值在Noda Time中具有关联的时区;   特别是只是"日期和时间固定在运行代码的计算机的本地时间

    现在听起来更像是文档试图传达的定义。

    或许,其他人可以提出比“' Raw&#39 ;;更好的词汇;但问题是,请将本地'本地'的真正含义告诉我们。因为'本地'在软件和生活中具有非常真实和非常有用的含义。

    因此,我们是否可以将Local[Date][Time]类重命名为Raw[Date][Time]并(可选)添加名为Local[Date][Time]的新类, 绑定到计算机' s当地时区?


    @Michal& @J ...... -

    我们遇到的问题并不是在{&#39}我们的'中理解LocalDateTime。本地(因为它是无区域的)。我们在LocalDateTime中遇到的问题是 无区域。实质上,根据定义,LocalDateTime 应该是一种特殊类型的ZonedDateTime。 (就像UTC在概念上(具体而言)是一种特殊类型的ZonedDateTime。因此,UTC可以拥有它自己的一组类型,例如:Utc[Date][Time];在给定正确的问题域的情况下可能非常有用。而且因为UtcDateTime尚未被采纳,我们可以在不干扰NodaTime的情况下创建这样的概念。)

    回到我们的问题,例如:如果我有两个ZonedDateTimes,一个来自纽约,另一个来自西雅图,我想从我当前的位置研究这两个ZonedDateTimes(让我们说:达拉斯)。我想写...

    LocalDateTime fromNy = newYork.LocalDateTime; 
    LocalDateTime fromWa = seattle.LocalDateTime;
    

    但相反,我得到两个不相关的本地日期时间,彼此之间完全没有关系。事实上,如果不是var名称,我不知道哪个是哪个。

    我想要的是两个ZonedDateTimes已经转换为我的本地时区,正如属性名称所暗示的那样。现在,这两个 LocalDateTime 值(其中LocalDateTime是特殊类型的ZonedDateTime)具有相关含义。我知道通过以下方式,我可以得到一些与我想要的相近的东西;但它很乱,没有传达相同的语义,也没有时区信息。

    DateTimeZone ct = BclDateTimeZone.ForSystemDefault();
    LocalDateTime tx1 = newYork.WithZone(ct);
    LocalDateTime tx2 = seattle.WithZone(ct);
    

    我还希望能够再次转换这些值:

    ZonedDateTime wa = tx2.WithZone(seattleTimeZone);
    ZonedDateTime nw = tx2.WithZone(nyTimeZone);
    

    这也允许:

    instant.InUtc();
    instant.InZone(zone);
    instant.InLocal();
    

    因此能够将即时时间映射到3个最常见的时区; UTC,本地和其他。但我不能,因为LocalDateTime不是特殊类型的ZonedDateTime。

    恕我直言,NodaTime 1.x很不错,但它不够灵活(或流畅),不适合黄金时段使用。但好消息是,它离它不远。希望在2.0(或更早)中可以解决这些问题。

    @Michal - 我喜欢你对Noda[Date][Time]的看法,而不是Raw[Date][Time]

1 个答案:

答案 0 :(得分:2)

你可能会对此感到困惑的是:

LocalDateTime =特定日历中的通用时间(例如Gregorian),但由于没有附加TimeZone,您无法区分全球时间线上发生的确切点。想象一下这只是一个普通的价值。例如。 14:00。你不知道究竟什么时候14:00,因为你错过了TimeZone的所在。

特定时区内的

ZonedDateTime = LocalDateTime(您可能想象为LocalDateTime)。

我可能同意你的说法,它有点误导。我希望将NodaDateTimeZonedDateTime称为LocalDateTime,因为它似乎更合乎逻辑。

编辑 - 发表评论

就个人而言,如果你坚持LocalDateTimeInstant,我很少使用ZonedDateTime你可能会摆脱很多麻烦。有一个非常好的概述图表转换类型:

取自:nodatime.org - User Guide - Converting Between Types

nodatime.org - User Guide - Converting Between Types

因此,在您的情况下,您要执行的操作是从特定的ZoneDateTime转换为Instant,然后返回到您想要的ZonedDateTime(您的系统tz)

E.g。

var myTz = BclDateTimeZone.ForSystemDefault();

var fromNy = SystemClock.Instance.Now.InZone(DateTimeZoneProviders.Tzdb["America/New_York"]);
// fromNy = 2015-03-22T08:28:56 America/New_York (-04)

var fromLa = SystemClock.Instance.Now.InZone(DateTimeZoneProviders.Tzdb["America/Los_Angeles"]);
// fromLa = 2015-03-22T05:28:56 America/Los_Angeles (-07)

var fromNyInMyTz = fromNy.ToInstant().InZone(myTz);
// localFromNy = 2015-03-22T12:28:56 GMT Standard Time (+00)

var fromLaInMyTz = fromLa.ToInstant().InZone(myTz);
// localFromLa = 2015-03-22T12:28:56 GMT Standard Time (+00)

您还可以创建扩展方法:

public static class NodaExtensions
{
    public static ZonedDateTime InUtc(this ZonedDateTime dt)
    {
        return dt.ToInstant().InUtc();
    }
    public static ZonedDateTime InZone(this ZonedDateTime dt, DateTimeZone tz)
    {
        return dt.ToInstant().InZone(tz);
    }
    public static ZonedDateTime InLocal(this ZonedDateTime dt)
    {
        return dt.ToInstant().InZone(BclDateTimeZone.ForSystemDefault());
    }
}

允许:

var fromNyInUtc = fromNy.InUtc();
var fromLaInUtc = fromLa.InUtc();

var fromNyInZone = fromNy.InZone(myTz);
var fromLaInZone = fromLa.InZone(myTz);

var fromNyInLocal = fromNy.InLocal();
var fromLaInLocal = fromLa.InLocal();

这是你想要的吗?