【问题标题】:Why does TimeSpan not have a Years property?为什么 TimeSpan 没有 Years 属性?
【发布时间】:2015-05-05 17:15:32
【问题描述】:

我正在编写一个转换器,它可以获取一个人的出生日期并以年为单位计算他们的年龄。我写了一些看起来像这样的东西:

public class DateOfBirthToAgeConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var date = value as DateTime?;
        if (date == null) return null;
        return (DateTime.Now - date).Years;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

我发现TimeSpan 上没有Years 属性,这是两个DateTime 对象相减的结果。我对此感到有些惊讶。我想过为什么可能没有Years。我认为这可能是因为闰日,但按照这种逻辑,由于夏令时,不应该有Days

没有Months 是有道理的,因为没有标准的月份长度。

我能够编写一些不同的代码来获得正确的年龄,但我仍然很想知道为什么TimeSpan 上没有YearsWeeks 属性。 有人知道原因吗?

【问题讨论】:

  • “为什么 X 没有 Y”通常不是最好的问题。您已经提到了准确定义一年的困难。
  • 即使由于夏令时两个日期之间的差异可能是 23 小时或 25 小时,但作为持续时间的“天”仍然具有 24 小时的固定定义。
  • 值得查看由 Jon Skeet 维护的 NodaTime 库。它是比内置的 DateTime 和 Timespan 类强得多的抽象。来自《马口》:blog.nodatime.org/2011/08/what-wrong-with-datetime-anyway.html
  • @Izkata - 不,21st July 的持续时间会更改(日历的属性)a day 的持续时间不(时间单位)
  • @EarthEngine 一个“SI 日”IS 86400 秒。 “公民日”可以是 86400 +/- 1 秒。但我们不以民用单位计量时间,我们使用国际单位制。

标签: c# datetime timespan


【解决方案1】:

TimeSpan 仅包含两个 DateTime 值之间的差异。不知道这个TimeSpan 在哪一年。这也是它没有Months 属性的原因。

示例:

TimeSpan.FromDays(60)

那是几个月? 1 还是 2


没有月份是有道理的,因为没有标准的月份长度。

由于闰年,也没有标准的年长度。

解决方法:如果你真的想显示一个近似值,那么 TimeSpan.TotalDays / 365.2425 就可以了。

编辑:但仅用于粗略估计,不适用于生日。 Henk Holterman 在 cmets 中指出,在生日计算中,闰日将每 4 年累积一次。看看here 计算生日。

【讨论】:

  • “大约”我的意思是“用户 X 在 StackOverflow 上已经 7 年了”。在这种情况下,这很好。对于生日(年龄)可能不是,但无论如何我想指出这一点。
  • 365.2425,平均公历年长度,运行良好。
  • @HenkHolterman 对于任何使用公历的东西。对农历、犹太历、中国历、恒星历等没有帮助。
  • @HenkHolterman 这不是一个近似值。这是公历的定义。您可能正在以日历不支持的方式定义“精确”。你有失败的例子吗?
  • 格雷格日历的定义不使用分数。这是一个近似值,有效结果纯属巧合。
【解决方案2】:

程序员的生活真的很艰难。

一年的长度是可变的。有些年份有365 天,有些年份有366 天。 According to the calendar,有些年份甚至可能缺少几天。如果说文化就更难了,因为中国农历一年有13个月。

月份的长度是可变的,这是众所周知的。这也是要知道在其他日历中情况可能会变得更糟。

由于夏令时,白天的长度是可变的,这不仅取决于文化,还取决于地理。

小时和分钟的长度是可变的,因为leap seconds。

似乎唯一可靠的是一秒钟的长度。所以在内部,时间跨度以秒(或毫秒,相同)为单位存储。

但是时间单位的可变性使得答案是“n 秒有多少(年/月/日/小时/分钟)?”总是不准确的。

这就是为什么开发人员最终会得到一个实用但不精确的解决方案。他们只是忽略了夏令时和闰秒。然而,由于人们几乎不问年月,他们只是决定不回答这些问题。

【讨论】:

    【解决方案3】:

    反问:没有参照点,一年是多长?

    由于 TimeSpan 没有固定的时间点,因此无法明确说明未知时间的一年有多长。在最简单的情况下,它可能是 365 或 366 天。影响结果的案例要多得多。

    【讨论】:

    • 已在问题中说明。而且您不需要 PoR,例如儒略年。
    • 根据谷歌,它是 365.242199 天。
    • 根据维基百科,它是 365.2425。
    • @IllidanS4 here 是一个很好的简短视频,解释了简单地定义一年是什么、可能有多长以及为什么得出一个数字不是那么简单的一些困难容易。
    • @Servy - 你真的认为我需要看那个吗?
    【解决方案4】:

    我想这可能是因为闰日,但按照这个逻辑, 由于夏令时,不应该有 Days。

    你说得有道理;减去两个日期不能理想地处理夏令时。如果日期是当地时间,您可能会得到意想不到的结果。

    夏令时的变化意味着当地时间的间隙或重叠,如果您使用日期进行计算,则会忽略这一点。因此,如果您想获得两个本地时间 DateTime 值之间的确切差异,您应该首先将它们转换为 UTC,因为它具有线性时间:

    TimeSpan diff = date1.ToUniversalTime() - date2.ToUniversalTime();
    

    TimeSpan 没有年份的原因是年份的长度不同。夏令时问题是您计算 TimeSpan 的方式的影响,可以规避,但没有可用于规避闰年的“线性年”。

    【讨论】:

    • 为什么投反对票?如果你不解释你认为错的地方是什么,它就无法改进答案。
    【解决方案5】:

    Timespan 只存储毫秒数。如果您有 (1000 * 60 * 60 * 24 * 365.5) 365.5 天的毫秒数,则无法知道该毫秒数是否跨越一整年和下一年,是否只是短短一年,或者是否跨越三年。与 30.5 天的毫秒数相同,可能跨越第二个月,可能不到一个月,可能跨越三个月。

    【讨论】:

    • 30.5 天可能是 2 个月,例如,如果从 1 月的最后一天开始。
    猜你喜欢
    • 2012-12-11
    • 2017-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-07
    • 2021-06-24
    • 1970-01-01
    相关资源
    最近更新 更多