В C # /. NET TimeSpan
имеет TotalDays
, TotalMinutes
и т.д. , но я не могу понять формулу для разницы всего месяца. Переменные дни в месяц и високосные годы меня сбивают с толку. Как я могу получить TotalMonths ?
Редактировать Извините за непонятность: я знаю, что на самом деле не могу получить это, TimeSpan
но я подумал, что использование TotalDays
и TotalMinutes
будет хорошим примером, чтобы выразить то, что я искал ... за исключением того, что я пытаюсь получить общее количество месяцев.
Пример: 25 декабря 2009 г. - 6 октября 2009 г. = 2 TotalMonths. С 6 октября по 5 ноября равно 0 месяцев. 6 ноября, 1 месяц. 6 декабря, 2 месяца
Ответы:
Вы не сможете получить это из a
TimeSpan
, потому что «месяц» - это переменная единица измерения. Вам придется рассчитать это самостоятельно, и вам нужно будет выяснить, как именно вы хотите, чтобы это работало.Например, должны ли даты быть такими, как
July 5, 2009
иAugust 4, 2009
давать разницу в один месяц или ноль месяцев? Если вы говорите, что он должен уступить один, то как насчетJuly 31, 2009
иAugust 1, 2009
? Является ли, что в месяц? Это просто разницаMonth
значений дат или это больше связано с фактическим промежутком времени? Логика определения всех этих правил нетривиальна, поэтому вам придется определить свое собственное и реализовать соответствующий алгоритм.Если все, что вам нужно, это просто разница в месяцах - полностью игнорируя значения даты - вы можете использовать это:
Обратите внимание, что это возвращает относительную разницу, что означает, что если
rValue
большеlValue
, то возвращаемое значение будет отрицательным. Если вам нужна абсолютная разница, вы можете использовать это:источник
(Я понимаю, что это старый вопрос, но ...)
Это относительно болезненно делать в чистом .NET. Я бы порекомендовал свою собственную библиотеку Noda Time , специально разработанную для таких вещей:
(Есть и другие варианты, например, если вам нужен только счет месяцев даже по годам, вы должны использовать
Period period = Period.Between(start, end, PeriodUnits.Months);
)источник
Period.Between
. Отредактировали код, чтобы он работал с NodaTime 1.3.1.Может быть, вы не хотите знать о долях месяца; А что насчет этого кода?
источник
Для начала вам нужно будет определить, что вы имеете в виду под TotalMonths.
Простое определение помещает месяц в 30,4 дня (365,25 / 12).
Кроме того, любое определение, включая дроби, кажется бесполезным, а более распространенное целочисленное значение (целые месяцы между датами) также зависит от нестандартных бизнес-правил.
источник
Я написал очень простой метод расширения
DateTime
иDateTimeOffset
для этого. Я хотел, чтобы он работал точно так же, как работаетTotalMonths
свойствоTimeSpan
: то есть возвращал количество полных месяцев между двумя датами, игнорируя любые неполные месяцы. Потому что он основан на том,DateTime.AddMonths()
что учитывает разную продолжительность месяца и возвращает то, что человек понимает как период месяцев.(К сожалению, вы не можете реализовать его как метод расширения в TimeSpan, потому что он не сохраняет информацию о фактических используемых датах, а в течение нескольких месяцев они важны.)
Код и тесты доступны на GitHub . Код очень простой:
И он проходит все эти модульные тесты:
источник
Вам нужно решить это самостоятельно, вне свиданий. То, как вы будете справляться с незавершенными днями в конце, будет зависеть от того, для чего вы хотите их использовать.
Один из способов - подсчитать месяц, а затем исправить дни в конце. Что-то вроде:
источник
Я бы сделал так:
источник
return (dtOther.Month - dtThis.Month) + 12 * (dtOther.Year - dtThis.Year);
На этот счет не так много четких ответов, потому что вы всегда предполагаете что-то.
Это решение рассчитывает между двумя датами месяцы между предполагаемым, что вы хотите сохранить день месяца для сравнения (это означает, что день месяца учитывается в вычислении)
Например, если у вас есть дата 30 января 2012 года, 29 февраля 2012 года будет не месяцем, а 01 марта 2013 года.
Он был протестирован довольно тщательно, вероятно, он будет очищен позже, когда мы его будем использовать, и принимает две даты вместо Timespan, что, вероятно, лучше. Надеюсь, это поможет кому-нибудь еще.
источник
Принятый ответ отлично работает, когда вам нужны полные месяцы.
Мне понадобились неполные месяцы. Вот решение, которое я придумал несколько месяцев:
Мне также нужна была разница в году при такой же потребности в неполные годы. Вот решение, которое я придумал:
источник
YearDifference
функции, когдаlValue.Month < rValue.Month
- я исправил это сейчас, вы можете проверить ...Старый вопрос я знаю, но может кому-то помочь. Я использовал принятый ответ @Adam выше, но затем проверил, составляет ли разница 1 или -1, а затем проверьте, есть ли разница в полном календарном месяце. Таким образом, 21.07.55 и 20.08.55 не будут полным месяцем, а 21.07.55 и 21.07.55 будут.
источник
источник
Проблема с месяцами в том, что это непростая мера - они не постоянный размер. Вам нужно будет определить свои правила для того, что вы хотите включить, и работать с ними. Например, с 1 января по 1 февраля - вы можете утверждать, что это 2 месяца, или вы можете сказать, что это один месяц. А как насчет «1 января 20:00» до «1 февраля 00:00» - это не совсем полный месяц. Это 0? 1? а как насчет наоборот (с 00:00 1 января до 20:00 1 февраля) ... 1? 2?
Сначала определите правила, а потом, боюсь, вам придется самому это кодировать ...
источник
Если вы хотите получить результат
1
между28th Feb
и1st March
:источник
Эта библиотека вычисляет разницу месяцев с учетом всех частей DateTime:
источник
Ниже приведен наиболее точный способ сделать это, поскольку определение «1 месяц» меняется в зависимости от того, какой сейчас месяц, и ни один из других ответов не учитывает это! Если вам нужна дополнительная информация о проблеме, которая не встроена в структуру, вы можете прочитать этот пост: Объект Real Timespan с .Years & .Months (однако чтение этого поста не обязательно для понимания и использования функции ниже, он работает на 100%, без присущих им неточностей приближения, которые любят использовать другие, - и не стесняйтесь заменять функцию .ReverseIt на встроенную функцию .Reverse, которая может быть у вас в вашем фреймворке (она здесь для полноты).
Обратите внимание, что вы можете получить любое количество точных дат / времени, секунд и минут или секунд, минут и дней в любом месте до лет (которые будут содержать 6 частей / сегментов). Если вы укажете два первых сегмента и ему больше года, он вернет «1 год и 3 месяца назад», а остальные не вернет, потому что вы запросили два сегмента. если ему всего несколько часов, он вернет только «2 часа и 1 минуту назад». Конечно, те же правила применяются, если вы указываете 1, 2, 3, 4, 5 или 6 сегментов (максимум 6, потому что секунды, минуты, часы, дни, месяцы, годы составляют только 6 типов). Это также исправит проблемы грамматики, такие как «минуты» против «минут», в зависимости от того, 1 минута или больше, одинаково для всех типов, а сгенерированная «строка» всегда будет грамматически правильной.
Вот несколько примеров для использования: bAllowSegments определяет, сколько сегментов показывать ... то есть: если 3, то возвращаемая строка будет (в качестве примера) ...
"3 years, 2 months and 13 days"
(не будет включать часы, минуты и секунды в качестве первых 3 значений времени категории), но если дата была более новой датой, например, несколько дней назад,"4 days, 1 hour and 13 minutes ago"
вместо этого вернется указание тех же сегментов (3) , поэтому все будет учтено!если bAllowSegments - 2, он вернется,
"3 years and 2 months"
а если 6 (максимальное значение) вернется"3 years, 2 months, 13 days, 13 hours, 29 minutes and 9 seconds"
, но напомню, что он будетNEVER RETURN
примерно так,"0 years, 0 months, 0 days, 3 hours, 2 minutes and 13 seconds ago"
поскольку он понимает, что в трех верхних сегментах нет данных о дате, и игнорирует их, даже если вы укажете 6 сегментов , так что не волнуйтесь :). Конечно, если есть сегмент с 0 в нем, он учтет это при формировании строки и будет отображаться как"3 days and 4 seconds ago"
и игнорируя часть «0 часов»! Наслаждайтесь и прокомментируйте, если хотите.Конечно, вам понадобится функция ReplaceLast, которая принимает исходную строку и аргумент, указывающий, что нужно заменить, и другой аргумент, указывающий, чем вы хотите его заменить, и он заменяет только последнее появление этой строки. ... я включил свой, если у вас его нет или вы не хотите его внедрять, так что вот он, он будет работать «как есть» без каких-либо изменений. Я знаю, что функция reverseit больше не нужна (существует в .net), но функции ReplaceLast и ReverseIt перенесены из дней pre-.net, поэтому, пожалуйста, извините, как устаревшая она может выглядеть (все еще работает на 100%, хотя использовала em более десяти лет, могу гарантировать, что они не содержат ошибок) ... :). веселит.
источник
Если вам нужно точное число, вы не можете использовать только временной интервал, так как вам нужно знать, в какие месяцы вы имеете дело, и имеете ли вы дело с високосным годом, как вы сказали.
Либо выберите приблизительное число, либо немного поиграйте с исходными DateTimes
источник
http://www.astro.uu.nl/~strous/AA/en/reken/juliaansedag.html
Если вы можете преобразовать время из григорианской даты в число дней по юлианскому календарю, вы можете просто создать оператор для сравнения числа зулианских дней, который может иметь тип double, чтобы получить месяцы, дни, секунды и т. Д. Ознакомьтесь с приведенным выше ссылка на алгоритм преобразования григорианского на юлианский.
источник
В idiomatic-C # нет встроенного способа сделать это точно. Есть некоторые обходные пути, такие как этот пример CodeProject, который люди уже кодировали.
источник
Если вы имеете дело с месяцами и годами, вам нужно что-то, что знает, сколько дней в каждом месяце и какие годы являются високосными.
Войдите в григорианский календарь (и другие реализации Календаря, зависящие от культуры ).
Хотя Календарь не предоставляет методов для прямого вычисления разницы между двумя моментами времени, у него есть такие методы, как
источник
источник
Метод возвращает список, содержащий 3 элемента, первый - год, второй - месяц, а конечный элемент - день:
источник
Вот мой вклад в улучшение разницы в месяцах, который я считаю точным:
Использование:
Вы можете создать другой метод под названием DiffYears и применить ту же логику, что и выше, и AddYears вместо AddMonths в цикле while.
источник
Поздно в игру, но я полагаю, что это может быть кому-то полезно. Большинство людей склонны измерять от месяца к месяцу по дате, за исключением того факта, что месяцы бывают разными. Используя этот образ мыслей, я создал один лайнер, который сравнивает для нас даты. Используя следующий процесс.
Если год на конец не больше, мы выполняем то же, что и 2A / 2B, но без добавления 12 месяцев, потому что нам не нужно оценивать год.
источник
В моем понимании этого ответа также используется метод расширения , но он может возвращать как положительный, так и отрицательный результат.
Пара тестов:
источник
Комбинируя два из приведенных выше ответов, можно получить еще один метод расширения:
Спасибо @AdamRobinson и @MarkWhittaker
источник
Рассчитайте количество месяцев между двумя датами:
источник