我正在写一个转换器,它取一个人的出生日期并生成他们的年龄。我写了一些看起来像这样的东西:
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();
}
}
我发现在Years
上没有TimeSpan
属性是由两个DateTime
对象的减法产生的。我对此感到有些惊讶。我想到为什么可能没有Years
。我认为可能是因为闰日,但按照这个逻辑,由于夏令时,不应该有Days
。
没有Months
是有道理的,因为没有标准的月份长度。
我能够写一些不同的代码来获得正确的年龄,但我仍然想知道为什么在Years
上没有Weeks
或TimeSpan
属性。有谁知道原因?
程序员的生活真的很难。
年份的长短是多变的。有些年有365
天,有些有366
天。 According to the calendar,有些年甚至可能有失踪的日子。如果谈论文化,由于中国农历一年可以有13个月,因此变得更加困难。
月份的长度是可变的,这是众所周知的。这也是要知道在其他日历中事情会变得更糟。
由于夏令时,一天的长度是可变的,这不仅取决于文化,还取决于地理。
由于leap seconds,小时和分钟的长度是可变的。
似乎唯一可靠的是一秒钟的长度。因此在内部,时间跨度以秒(或毫秒,相同)存储。
但时间单位的变化使答案“n
秒的数量(年/月/日/小时/分钟)?”永远不准确。
这就是为什么开发人员最终会得到一个实用但不精确的解决方案。他们完全忽略了夏令时和闰秒。然而,由于人们几乎不会问几年和几个月,他们只是决定不回答这些问题。
TimeSpan
仅包含两个DateTime
值之间的差异。不知道这个TimeSpan
在哪一年。这也是为什么它没有Months
财产。
例:
TimeSpan.FromDays(60)
那几个月了? 1还是2?
缺少月份是有道理的,因为没有标准的月份长度。
由于闰年,没有标准的年份长度。
解决方法:如果你真的想要显示一个近似值,那么做TimeSpan.TotalDays / 365
就可以了。
编辑:但仅适用于粗略估计而非生日。在生日计算中,Henk Holterman在评论中指出,闰日将每4年累积一次。看看here来计算生日。
修辞问题:没有参考点,一年有多长?
由于TimeSpan没有固定的时间点,因此无法明确说明未知时间每年会持续多长时间。在最简单的情况下,它可能是365或366天。有更多的案例会影响结果。
我认为这可能是因为闰日,但按照这个逻辑,因为夏令时不应该有天。
你有一点意见;减去两个日期并不能理想地处理夏令时。如果日期是当地时间,您可能会得到意外的结果。
夏令时的变化意味着当地时间的间隙或重叠,如果您使用日期进行计算,则会忽略这一点。因此,如果您想获得两个本地时间的DateTime
值之间的确切差异,您应该首先将它们转换为UTC,因为它具有线性时间:
TimeSpan diff = date1.ToUniversalTime() - date2.ToUniversalTime();
TimeSpan
没有多年的原因是年份的长度不同。夏令时问题是你如何计算TimeSpan
并且可以被规避的结果,但是没有“线性年”可以用来规避闰年。
Timespan只存储毫秒数。如果你有(1000 * 60 * 60 * 24 * 365.5)365.5天的毫秒数,那么就不可能知道这个毫秒数是否会跨越一整年并进入下一年,如果它只是短短一年,或者跨越一年三年。相同的是30.5天的毫秒,可能会持续到第二个月,可能不到一个月,可能跨越三个月。