Почему TimeSpan не обладает свойством Years?
Я писал конвертер, который принимает человека на дату рождения и производит их возраст в годах. Я написал что-то вроде:
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
нет свойства Years
или Weeks
. Кто-нибудь знает причину?
Ответы
Ответ 1
Жизнь программиста действительно тяжелая.
Длина года является переменной. Некоторые годы имеют 365
дней, а некоторые - 366
дней. Согласно календарю, у некоторых лет могут быть даже пропущенные дни. Если говорить о культуре, то это становится сложнее, поскольку китайский лунный календарь может иметь 13 месяцев в году.
Длина месяца является переменной, и это хорошо известно. Это также означает, что в других календарях все может ухудшиться.
Продолжительность дня является переменной из-за экономии летнего времени, и это зависит не только от культуры, но и от географии.
Длина часа и минуты являются переменными, из-за високосных секунд с.
Кажется, единственное, что заслуживает доверия, это длина секунды. Таким образом, внутреннее время хранится в секундах (или миллисекундах, что то же самое).
Но изменчивость единиц времени дает ответ "сколько (лет/месяцев/дней/часов/минут) за n
секунд?" быть всегда неточным.
Вот почему разработчики получают решение, которое полезно на практике, но не является точным. Они просто игнорируют переход на летнее время и дополнительные секунды. Однако, поскольку люди почти не задают вопросы о годах и месяцах, они просто решили не отвечать на эти вопросы.
Ответ 2
TimeSpan
содержит только разницу между двумя значениями DateTime
. Неизвестно, в каком году этот TimeSpan
. Это также то, почему у него нет свойства Months
.
Пример:
TimeSpan.FromDays(60)
Сколько месяцев это? 1 или 2?
Отсутствие месяцев имело смысл, поскольку нет стандартной продолжительности месяца.
Также нет стандартной продолжительности года из-за високосных лет.
Обходной путь: Если вы действительно хотите отобразить приблизительное значение, тогда выполнение TimeSpan.TotalDays/365
подойдет.
Изменение: Но только для приблизительных оценок, а не для дней рождения. В расчете дня рождения високосные дни будут накапливаться каждые 4 года, как отметил Хенк Холтерман в комментариях. Посмотрите здесь для расчета дней рождения.
Ответ 3
Риторический вопрос: без точки отсчета, как долго проходит год?
Поскольку TimeSpan не имеет фиксированной точки во времени, невозможно однозначно сказать, как долго будет длиться год в неизвестное время. В простейшем случае это может быть 365 или 366 дней. Значительно больше случаев, которые повлияют на результат.
Ответ 4
Я понял, что это может быть из-за високосного дня, но по этой логике, не должно быть Дней из-за летнего сбережения.
У вас есть точка; вычитание двух дат идеально подходит для экономии дневного света. Если даты являются местным временем, вы можете получить неожиданный результат.
Изменение летнего времени означает пробел или перекрытие в локальное время, и это игнорируется, если вы выполняете расчеты с датами. Итак, если вы хотите получить точную разницу между двумя значениями DateTime
, которые являются местным временем, вы должны сначала преобразовать их в UTC, так как это имеет линейное время:
TimeSpan diff = date1.ToUniversalTime() - date2.ToUniversalTime();
Причина, по которой TimeSpan
не имеет лет, состоит в том, что годы различаются по длине. Проблема с дневным сбережением является следствием того, как вы вычисляете TimeSpan
, и ее можно обойти, но нет "линейных лет", которые вы можете использовать, чтобы обойти високосные годы.
Ответ 5
Timespan просто сохраняет количество миллисекунд. Если у вас есть (1000 * 60 * 60 * 24 * 365,5) 365,5 дней в миллисекундах, невозможно узнать, охватывает ли это количество миллисекундов целый год и в следующем, если это просто меньше года, или если оно охватывает три года. То же самое с 30,5 днями в миллисекундах, может занять второй месяц, может быть меньше месяца, может охватывать три месяца.