Если вы не кодируете веб-приложение, убедитесь, что ваш класс, в котором выполняется @Autowiring, является весенним бобом. Как правило, весенний контейнер не будет знать о классе, который мы могли бы назвать весенним бобом. Мы должны рассказать весенний контейнер о наших весенних классах.
Этого можно достичь путем настройки в appln-contxt или лучший способ - аннотировать класс как @Component и, пожалуйста, не создавайте аннотированный класс, используя новый оператор. Убедитесь, что вы получили его из контекста Appln, как показано ниже.
@Component
public class MyDemo {
@Autowired
private MyService myService;
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("test");
ApplicationContext ctx=new ClassPathXmlApplicationContext("spring.xml");
System.out.println("ctx>>"+ctx);
Customer c1=null;
MyDemo myDemo=ctx.getBean(MyDemo.class);
System.out.println(myDemo);
myDemo.callService(ctx);
}
public void callService(ApplicationContext ctx) {
// TODO Auto-generated method stub
System.out.println("---callService---");
System.out.println(myService);
myService.callMydao();
}
}
Предполагая, что день месяца не имеет значения (т.е. разница между 2011.1.1 и 2010.12.31 равна 1), с date1> date2, дающим положительное значение, а date2> date1 - отрицательное значение
((date1.Year - date2.Year) * 12) + date1.Month - date2.Month
Или, если вы хотите приблизительное количество «средних месяцев» между двумя датами, следующее должно работать для всех, но очень больших различий в дате.
date1.Subtract(date2).Days / (365.25 / 12)
Обратите внимание, что если вы должны использовать последнее решение, тогда ваши юнит-тесты должны указывать самый широкий диапазон дат, для которого ваше приложение разработано для работы и соответствующим образом оценивает результаты расчета.
Обновление (с помощью Gary )
Если использовать метод «средних месяцев», то для более «среднего числа дней в году» используется несколько более точный номер 365.2425 .
Вот гораздо более сжатое решение, использующее VB.Net DateDiff только для Year, Month, Day. Вы также можете загрузить библиотеку DateDiff в C #.
date1 должно быть & lt; = date2
VB.NET
Dim date1 = Now.AddDays(-2000)
Dim date2 = Now
Dim diffYears = DateDiff(DateInterval.Year, date1, date2) - If(date1.DayOfYear > date2.DayOfYear, 1, 0)
Dim diffMonths = DateDiff(DateInterval.Month, date1, date2) - diffYears * 12 - If(date1.Day > date2.Day, 1, 0)
Dim diffDays = If(date2.Day >= date1.Day, date2.Day - date1.Day, date2.Day + (Date.DaysInMonth(date1.Year, date1.Month) - date1.Day))
C #
DateTime date1 = Now.AddDays(-2000);
DateTime date2 = Now;
int diffYears = DateDiff(DateInterval.Year, date1, date2) - date1.DayOfYear > date2.DayOfYear ? 1 : 0;
int diffMonths = DateDiff(DateInterval.Month, date1, date2) - diffYears * 12 - date1.Day > date2.Day ? 1 : 0;
int diffDays = date2.Day >= date1.Day ? date2.Day - date1.Day : date2.Day + (System.DateTime.DaysInMonth(date1.Year, date1.Month) - date1.Day);
Чтобы получить разницу в месяцах (включая начало и конец включительно), независимо от дат:
DateTime start = new DateTime(2013, 1, 1);
DateTime end = new DateTime(2014, 2, 1);
var diffMonths = (end.Month + end.Year * 12) - (start.Month + start.Year * 12);
start
и end
идентичны. Затем вы получаете результат 1. Как это правильно? Почему вы добавляете 1 к результату? Кто голосует за этот ответ: - /?
– paul
18 December 2014 в 07:35
Использовать Noda Time :
LocalDate start = new LocalDate(2013, 1, 5);
LocalDate end = new LocalDate(2014, 6, 1);
Period period = Period.Between(start, end, PeriodUnits.Months);
Console.WriteLine(period.Months); // 16
Я проверил использование этого метода в VB.NET через MSDN, и кажется, что он имеет много обычаев. В C # такого встроенного метода нет. (Даже это не очень хорошая идея), вы можете вызвать VB в C #.
Microsoft.VisualBasic.dll
в ваш проект в качестве ссылки Microsoft.VisualBasic.DateAndTime.DateDiff
в вашем коде Microsoft.VisualBasic.dll
должен быть загружен, но время, необходимое для этого, незначительно. Нет никакой причины обманывать себя из тщательно проверенных и полезных функций только потому, что вы решили написать свою программу на C #. (Это касается таких вещей, как My.Application.SplashScreen
.)
– Cody Gray♦
9 January 2011 в 13:43
using
, но я сомневаюсь, что будет какой-либо серьезный ущерб.
– Cody Gray♦
9 January 2011 в 14:21
DateAndTime.Year()
, учитывая, что DateTime
имеет свойство Year
. Он существует только для того, чтобы сделать VB.NET более похожим на VB6. Будучи бывшим программистом VB6, я могу это оценить ;-)
– Adam Ralph
10 January 2011 в 11:34
Если вы хотите точное количество полных месяцев, всегда положительный (2000-01-15, 2000-02-14 возвращает 0), учитывая полный месяц, когда вы достигнете того же дня в следующем месяце (что-то вроде возраста вычисление)
public static int GetMonthsBetween(DateTime from, DateTime to)
{
if (from > to) return GetMonthsBetween(to, from);
var monthDiff = Math.Abs((to.Year * 12 + (to.Month - 1)) - (from.Year * 12 + (from.Month - 1)));
if (from.AddMonths(monthDiff) > to || to.Day < from.Day)
{
return monthDiff - 1;
}
else
{
return monthDiff;
}
}
Исправление причины: старый код не был прав в некоторых случаях, например:
new { From = new DateTime(1900, 8, 31), To = new DateTime(1901, 8, 30), Result = 11 },
Test cases I used to test the function:
var tests = new[]
{
new { From = new DateTime(1900, 1, 1), To = new DateTime(1900, 1, 1), Result = 0 },
new { From = new DateTime(1900, 1, 1), To = new DateTime(1900, 1, 2), Result = 0 },
new { From = new DateTime(1900, 1, 2), To = new DateTime(1900, 1, 1), Result = 0 },
new { From = new DateTime(1900, 1, 1), To = new DateTime(1900, 2, 1), Result = 1 },
new { From = new DateTime(1900, 2, 1), To = new DateTime(1900, 1, 1), Result = 1 },
new { From = new DateTime(1900, 1, 31), To = new DateTime(1900, 2, 1), Result = 0 },
new { From = new DateTime(1900, 8, 31), To = new DateTime(1900, 9, 30), Result = 0 },
new { From = new DateTime(1900, 8, 31), To = new DateTime(1900, 10, 1), Result = 1 },
new { From = new DateTime(1900, 1, 1), To = new DateTime(1901, 1, 1), Result = 12 },
new { From = new DateTime(1900, 1, 1), To = new DateTime(1911, 1, 1), Result = 132 },
new { From = new DateTime(1900, 8, 31), To = new DateTime(1901, 8, 30), Result = 11 },
};
new { From = new DateTime(2015, 12, 31), To = new DateTime(2015, 6, 30), Result = 6 }
тест завершится неудачно, так как результат равен 5.
– Cristian Badila
16 December 2015 в 18:58
new { From = new DateTime(2015, 12, 31), To = new DateTime(2016, 06, 30), Result = 6 }
. «Ошибка» лежит в коде to.Day < from.Day
, который не учитывает, что месяцы могут заканчиваться в другом «день месяца». В этом случае с 31 декабря 2015 года до 30 июня 2016 года пройдут 6 полных месяцев (с июня 30 дней), но ваш код вернет 5.
– Cristian Badila
18 December 2015 в 14:13
На это не так много четких ответов, потому что вы всегда принимаете вещи.
Это решение вычисляет между двумя датами месяцев между предположением, что вы хотите сохранить день месяца для сравнения (что означает что день месяца учитывается в расчете)
Пример, если у вас есть дата 30 января 2012 года, 29 февраля 2012 года не будет месяца, а 01 марта 2013 года.
Он был протестирован довольно тщательно, возможно, его очистят позже, когда мы его используем, но здесь:
private static int TotalMonthDifference(DateTime dtThis, DateTime dtOther)
{
int intReturn = 0;
bool sameMonth = false;
if (dtOther.Date < dtThis.Date) //used for an error catch in program, returns -1
intReturn--;
int dayOfMonth = dtThis.Day; //captures the month of day for when it adds a month and doesn't have that many days
int daysinMonth = 0; //used to caputre how many days are in the month
while (dtOther.Date > dtThis.Date) //while Other date is still under the other
{
dtThis = dtThis.AddMonths(1); //as we loop, we just keep adding a month for testing
daysinMonth = DateTime.DaysInMonth(dtThis.Year, dtThis.Month); //grabs the days in the current tested month
if (dtThis.Day != dayOfMonth) //Example 30 Jan 2013 will go to 28 Feb when a month is added, so when it goes to march it will be 28th and not 30th
{
if (daysinMonth < dayOfMonth) // uses day in month max if can't set back to day of month
dtThis.AddDays(daysinMonth - dtThis.Day);
else
dtThis.AddDays(dayOfMonth - dtThis.Day);
}
if (((dtOther.Year == dtThis.Year) && (dtOther.Month == dtThis.Month))) //If the loop puts it in the same month and year
{
if (dtOther.Day >= dayOfMonth) //check to see if it is the same day or later to add one to month
intReturn++;
sameMonth = true; //sets this to cancel out of the normal counting of month
}
if ((!sameMonth)&&(dtOther.Date > dtThis.Date))//so as long as it didn't reach the same month (or if i started in the same month, one month ahead, add a month)
intReturn++;
}
return intReturn; //return month
}
Public Class ClassDateOperation
Private prop_DifferenceInDay As Integer
Private prop_DifferenceInMonth As Integer
Private prop_DifferenceInYear As Integer
Public Function DayMonthYearFromTwoDate(ByVal DateStart As Date, ByVal DateEnd As Date) As ClassDateOperation
Dim differenceInDay As Integer
Dim differenceInMonth As Integer
Dim differenceInYear As Integer
Dim myDate As Date
DateEnd = DateEnd.AddDays(1)
differenceInYear = DateEnd.Year - DateStart.Year
If DateStart.Month <= DateEnd.Month Then
differenceInMonth = DateEnd.Month - DateStart.Month
Else
differenceInYear -= 1
differenceInMonth = (12 - DateStart.Month) + DateEnd.Month
End If
If DateStart.Day <= DateEnd.Day Then
differenceInDay = DateEnd.Day - DateStart.Day
Else
myDate = CDate("01/" & DateStart.AddMonths(1).Month & "/" & DateStart.Year).AddDays(-1)
If differenceInMonth <> 0 Then
differenceInMonth -= 1
Else
differenceInMonth = 11
differenceInYear -= 1
End If
differenceInDay = myDate.Day - DateStart.Day + DateEnd.Day
End If
prop_DifferenceInDay = differenceInDay
prop_DifferenceInMonth = differenceInMonth
prop_DifferenceInYear = differenceInYear
Return Me
End Function
Public ReadOnly Property DifferenceInDay() As Integer
Get
Return prop_DifferenceInDay
End Get
End Property
Public ReadOnly Property DifferenceInMonth As Integer
Get
Return prop_DifferenceInMonth
End Get
End Property
Public ReadOnly Property DifferenceInYear As Integer
Get
Return prop_DifferenceInYear
End Get
End Property
End Class
У вас может быть такая функция.
Например, с 2012/12/27 по 2012/12/29 становится 3 дня. Аналогично, с 2012/12/15 до 2013/01/15 становится 2 месяца, потому что до 2013/01/14 это 1 месяц. с 15-го года начался второй месяц.
Вы можете удалить «=» во втором условии if, если вы не хотите включать оба дня в расчет. то есть с 2012/12/15 до 2013/01/15 составляет 1 месяц.
public int GetMonths(DateTime startDate, DateTime endDate)
{
if (startDate > endDate)
{
throw new Exception("Start Date is greater than the End Date");
}
int months = ((endDate.Year * 12) + endDate.Month) - ((startDate.Year * 12) + startDate.Month);
if (endDate.Day >= startDate.Day)
{
months++;
}
return months;
}
Расширенная структура Kirks с ToString (формат) и Duration (long ms)
public struct DateTimeSpan
{
private readonly int years;
private readonly int months;
private readonly int days;
private readonly int hours;
private readonly int minutes;
private readonly int seconds;
private readonly int milliseconds;
public DateTimeSpan(int years, int months, int days, int hours, int minutes, int seconds, int milliseconds)
{
this.years = years;
this.months = months;
this.days = days;
this.hours = hours;
this.minutes = minutes;
this.seconds = seconds;
this.milliseconds = milliseconds;
}
public int Years { get { return years; } }
public int Months { get { return months; } }
public int Days { get { return days; } }
public int Hours { get { return hours; } }
public int Minutes { get { return minutes; } }
public int Seconds { get { return seconds; } }
public int Milliseconds { get { return milliseconds; } }
enum Phase { Years, Months, Days, Done }
public string ToString(string format)
{
format = format.Replace("YYYY", Years.ToString());
format = format.Replace("MM", Months.ToString());
format = format.Replace("DD", Days.ToString());
format = format.Replace("hh", Hours.ToString());
format = format.Replace("mm", Minutes.ToString());
format = format.Replace("ss", Seconds.ToString());
format = format.Replace("ms", Milliseconds.ToString());
return format;
}
public static DateTimeSpan Duration(long ms)
{
DateTime dt = new DateTime();
return CompareDates(dt, dt.AddMilliseconds(ms));
}
public static DateTimeSpan CompareDates(DateTime date1, DateTime date2)
{
if (date2 < date1)
{
var sub = date1;
date1 = date2;
date2 = sub;
}
DateTime current = date1;
int years = 0;
int months = 0;
int days = 0;
Phase phase = Phase.Years;
DateTimeSpan span = new DateTimeSpan();
while (phase != Phase.Done)
{
switch (phase)
{
case Phase.Years:
if (current.AddYears(years + 1) > date2)
{
phase = Phase.Months;
current = current.AddYears(years);
}
else
{
years++;
}
break;
case Phase.Months:
if (current.AddMonths(months + 1) > date2)
{
phase = Phase.Days;
current = current.AddMonths(months);
}
else
{
months++;
}
break;
case Phase.Days:
if (current.AddDays(days + 1) > date2)
{
current = current.AddDays(days);
var timespan = date2 - current;
span = new DateTimeSpan(years, months, days, timespan.Hours, timespan.Minutes, timespan.Seconds, timespan.Milliseconds);
phase = Phase.Done;
}
else
{
days++;
}
break;
}
}
return span;
}
}
Это ответ на ответ Кирка Волла. У меня недостаточно очков репутации, чтобы ответить на комментарий еще ...
Мне понравилось решение Кирка, и он собирался бесстыдно разорвать его и использовать в моем коде, но когда я просмотрел его, я понял, что это слишком сложно. Ненужное переключение и цикл, а также открытый конструктор, который бессмысленно использовать.
Вот мой переписывающий:
public class DateTimeSpan {
private DateTime _date1;
private DateTime _date2;
private int _years;
private int _months;
private int _days;
private int _hours;
private int _minutes;
private int _seconds;
private int _milliseconds;
public int Years { get { return _years; } }
public int Months { get { return _months; } }
public int Days { get { return _days; } }
public int Hours { get { return _hours; } }
public int Minutes { get { return _minutes; } }
public int Seconds { get { return _seconds; } }
public int Milliseconds { get { return _milliseconds; } }
public DateTimeSpan(DateTime date1, DateTime date2) {
_date1 = (date1 > date2) ? date1 : date2;
_date2 = (date2 < date1) ? date2 : date1;
_years = _date1.Year - _date2.Year;
_months = (_years * 12) + _date1.Month - _date2.Month;
TimeSpan t = (_date2 - _date1);
_days = t.Days;
_hours = t.Hours;
_minutes = t.Minutes;
_seconds = t.Seconds;
_milliseconds = t.Milliseconds;
}
public static DateTimeSpan CompareDates(DateTime date1, DateTime date2) {
return new DateTimeSpan(date1, date2);
}
}
Usage1, почти то же самое:
void Main()
{
DateTime compareTo = DateTime.Parse("8/13/2010 8:33:21 AM");
DateTime now = DateTime.Parse("2/9/2012 10:10:11 AM");
var dateSpan = new DateTimeSpan(compareTo, now);
Console.WriteLine("Years: " + dateSpan.Years);
Console.WriteLine("Months: " + dateSpan.Months);
Console.WriteLine("Days: " + dateSpan.Days);
Console.WriteLine("Hours: " + dateSpan.Hours);
Console.WriteLine("Minutes: " + dateSpan.Minutes);
Console.WriteLine("Seconds: " + dateSpan.Seconds);
Console.WriteLine("Milliseconds: " + dateSpan.Milliseconds);
}
Usage2, похоже:
void Main()
{
DateTime compareTo = DateTime.Parse("8/13/2010 8:33:21 AM");
DateTime now = DateTime.Parse("2/9/2012 10:10:11 AM");
Console.WriteLine("Years: " + DateTimeSpan.CompareDates(compareTo, now).Years);
Console.WriteLine("Months: " + DateTimeSpan.CompareDates(compareTo, now).Months);
Console.WriteLine("Days: " + DateTimeSpan.CompareDates(compareTo, now).Days);
Console.WriteLine("Hours: " + DateTimeSpan.CompareDates(compareTo, now).Hours);
Console.WriteLine("Minutes: " + DateTimeSpan.CompareDates(compareTo, now).Minutes);
Console.WriteLine("Seconds: " + DateTimeSpan.CompareDates(compareTo, now).Seconds);
Console.WriteLine("Milliseconds: " + DateTimeSpan.CompareDates(compareTo, now).Milliseconds);
}
Вот комплексное решение для возврата DateTimeSpan
, похожего на TimeSpan
, за исключением того, что оно включает в себя все компоненты даты в дополнение к компонентам времени.
Использование:
void Main()
{
DateTime compareTo = DateTime.Parse("8/13/2010 8:33:21 AM");
DateTime now = DateTime.Parse("2/9/2012 10:10:11 AM");
var dateSpan = DateTimeSpan.CompareDates(compareTo, now);
Console.WriteLine("Years: " + dateSpan.Years);
Console.WriteLine("Months: " + dateSpan.Months);
Console.WriteLine("Days: " + dateSpan.Days);
Console.WriteLine("Hours: " + dateSpan.Hours);
Console.WriteLine("Minutes: " + dateSpan.Minutes);
Console.WriteLine("Seconds: " + dateSpan.Seconds);
Console.WriteLine("Milliseconds: " + dateSpan.Milliseconds);
}
Выходы:
Years: 1 Months: 5 Days: 27 Hours: 1 Minutes: 36 Seconds: 50 Milliseconds: 0
blockquote>Для удобства я включил логику в структуру
DateTimeSpan
, но вы можете перемещать методCompareDates
, где бы вы ни находились. Также обратите внимание: не имеет значения, какая дата предшествует другой.public struct DateTimeSpan { private readonly int years; private readonly int months; private readonly int days; private readonly int hours; private readonly int minutes; private readonly int seconds; private readonly int milliseconds; public DateTimeSpan(int years, int months, int days, int hours, int minutes, int seconds, int milliseconds) { this.years = years; this.months = months; this.days = days; this.hours = hours; this.minutes = minutes; this.seconds = seconds; this.milliseconds = milliseconds; } public int Years { get { return years; } } public int Months { get { return months; } } public int Days { get { return days; } } public int Hours { get { return hours; } } public int Minutes { get { return minutes; } } public int Seconds { get { return seconds; } } public int Milliseconds { get { return milliseconds; } } enum Phase { Years, Months, Days, Done } public static DateTimeSpan CompareDates(DateTime date1, DateTime date2) { if (date2 < date1) { var sub = date1; date1 = date2; date2 = sub; } DateTime current = date1; int years = 0; int months = 0; int days = 0; Phase phase = Phase.Years; DateTimeSpan span = new DateTimeSpan(); int officialDay = current.Day; while (phase != Phase.Done) { switch (phase) { case Phase.Years: if (current.AddYears(years + 1) > date2) { phase = Phase.Months; current = current.AddYears(years); } else { years++; } break; case Phase.Months: if (current.AddMonths(months + 1) > date2) { phase = Phase.Days; current = current.AddMonths(months); if (current.Day < officialDay && officialDay <= DateTime.DaysInMonth(current.Year, current.Month)) current = current.AddDays(officialDay - current.Day); } else { months++; } break; case Phase.Days: if (current.AddDays(days + 1) > date2) { current = current.AddDays(days); var timespan = date2 - current; span = new DateTimeSpan(years, months, days, timespan.Hours, timespan.Minutes, timespan.Seconds, timespan.Milliseconds); phase = Phase.Done; } else { days++; } break; } } return span; } }
34
дней для этой разницы во времени даты на самом деле это 35
timeanddate.com/date/…
– Deeptechtons
26 November 2012 в 05:36
31
, а дата «проходит через», месяцев с меньшим количеством дней. Я перевернул логику (так, что она идет от раннего к более позднему, чем наоборот), и теперь накапливает месяцы, не изменяя текущую дату (и, таким образом, проходя через промежуточные месяцы с меньшим количеством дней). Все еще не совсем уверен, какой идеальный результат должно быть при сравнении 10/31/2012
с 11/30/2012
. Сейчас результат - 1
месяц.
– Kirk Woll
26 November 2012 в 16:09
2020-02-29
- 2021-06-29
- он возвращает «1y 4m 1d», но значение должно быть «1y 4m 0d», правильно?
– Enigmativity
3 June 2015 в 09:29
Вот как мы подходим к этому:
public static int MonthDiff(DateTime date1, DateTime date2)
{
if (date1.Month < date2.Month)
{
return (date2.Year - date1.Year) * 12 + date2.Month - date1.Month;
}
else
{
return (date2.Year - date1.Year - 1) * 12 + date2.Month - date1.Month + 12;
}
}
Это из моей собственной библиотеки, вернет разницу между месяцами между двумя датами.
public static int MonthDiff(DateTime d1, DateTime d2)
{
int retVal = 0;
// Calculate the number of years represented and multiply by 12
// Substract the month number from the total
// Substract the difference of the second month and 12 from the total
retVal = (d1.Year - d2.Year) * 12;
retVal = retVal - d1.Month;
retVal = retVal - (12 - d2.Month);
return retVal;
}
Jan-31-2014
и Dec-31-2013
– Dave Cousineau
17 August 2014 в 03:31
Вы можете сделать
if ( date1.AddMonths(x) > date2 )
Вот мой вклад, чтобы получить разницу в месяцах, которые, как я считаю, точны:
namespace System
{
public static class DateTimeExtensions
{
public static Int32 DiffMonths( this DateTime start, DateTime end )
{
Int32 months = 0;
DateTime tmp = start;
while ( tmp < end )
{
months++;
tmp = tmp.AddMonths( 1 );
}
return months;
}
}
}
Использование:
Int32 months = DateTime.Now.DiffMonths( DateTime.Now.AddYears( 5 ) );
Вы можете создать другой метод под названием DiffYears и применять точно такую же логику, как указано выше, и AddYears вместо AddMonths в цикле while.
var dt1 = (DateTime.Now.Year * 12) + DateTime.Now.Month;
var dt2 = (DateTime.Now.AddMonths(-13).Year * 12) + DateTime.Now.AddMonths(-13).Month;
Console.WriteLine(dt1);
Console.WriteLine(dt2);
Console.WriteLine((dt1 - dt2));
Вот простое решение, которое работает хотя бы для меня. Скорее всего, это не самый быстрый результат, потому что он использует замечательную функцию AddMonth DateTime в цикле:
public static int GetMonthsDiff(DateTime start, DateTime end)
{
if (start > end)
return GetMonthsDiff(end, start);
int months = 0;
do
{
start = start.AddMonths(1);
if (start > end)
return months;
months++;
}
while (true);
}
int nMonths = 0;
if (FDate.ToDateTime().Year == TDate.ToDateTime().Year)
nMonths = TDate.ToDateTime().Month - FDate.ToDateTime().Month;
else
nMonths = (12 - FDate.Month) + TDate.Month;
Чтобы иметь возможность рассчитать разницу между двумя датами в месяцах, это совершенно логично, и это необходимо во многих бизнес-приложениях. Несколько кодеров, которые предоставили комментарии, такие как: какая разница в месяцах между «май 1,2010» и «16 июня 2010 года, какая разница в месяцах между 31 декабря 2010 года и 1 января 2011 года?», Не поняли самые основные бизнес-приложения.
Вот ответ на вышеупомянутые 2 комментария. Число месяцев между 1-м-май-2010 и 16-июн-2010 составляет 1 месяц, количество месяцев между 31 -dec-2010 и 1-jan-2011 - 0. Было бы очень глупо расчитывать их как 1,5 месяца и 1 секунду, как предлагали вышеперечисленные кодеры.
Люди, которые работали на кредитной карте, (g2)
Проблема в том, что такая функция не включена в C # или VB.NET, если на то пошло. Datediff учитывает только годы или компонент месяца, поэтому на самом деле бесполезно.
Вот некоторые реальные примеры того, где вам нужно и правильно может рассчитать месяцы:
Вы живете в краткосрочной прокате с 18 до 24 лет. Сколько месяцев вы там? Ответ прост - 6 месяцев
У вас есть счет в банке, где проценты рассчитываются и выплачиваются в конце каждого месяца. Вы депонируете деньги на 10-юн и выведете 29-окт (в том же году). Сколько месяцев вы интересуетесь? Очень простой ответ - 4 месяца (опять же, дополнительные дни не имеют значения)
В бизнес-приложениях, в большинстве случаев, когда вам нужно рассчитать месяцы, это потому, что вам нужно знать «полные» месяцы о том, как люди вычисляют время; не основанные на некоторых абстрактных / нерелевантных мыслях.
Вы можете использовать класс DateDiff библиотеки времени для .NET :
// ----------------------------------------------------------------------
public void DateDiffSample()
{
DateTime date1 = new DateTime( 2009, 11, 8, 7, 13, 59 );
DateTime date2 = new DateTime( 2011, 3, 20, 19, 55, 28 );
DateDiff dateDiff = new DateDiff( date1, date2 );
// differences
Console.WriteLine( "DateDiff.Months: {0}", dateDiff.Months );
// > DateDiff.Months: 16
// elapsed
Console.WriteLine( "DateDiff.ElapsedMonths: {0}", dateDiff.ElapsedMonths );
// > DateDiff.ElapsedMonths: 4
// description
Console.WriteLine( "DateDiff.GetDescription(6): {0}", dateDiff.GetDescription( 6 ) );
// > DateDiff.GetDescription(6): 1 Year 4 Months 12 Days 12 Hours 41 Mins 29 Secs
} // DateDiffSample
вы можете использовать следующее расширение: Код
public static class Ext
{
#region Public Methods
public static int GetAge(this DateTime @this)
{
var today = DateTime.Today;
return ((((today.Year - @this.Year) * 100) + (today.Month - @this.Month)) * 100 + today.Day - @this.Day) / 10000;
}
public static int DiffMonths(this DateTime @from, DateTime @to)
{
return (((((@to.Year - @from.Year) * 12) + (@to.Month - @from.Month)) * 100 + @to.Day - @from.Day) / 100);
}
public static int DiffYears(this DateTime @from, DateTime @to)
{
return ((((@to.Year - @from.Year) * 100) + (@to.Month - @from.Month)) * 100 + @to.Day - @from.Day) / 10000;
}
#endregion Public Methods
}
Реализация!
int Age;
int years;
int Months;
//Replace your own date
var d1 = new DateTime(2000, 10, 22);
var d2 = new DateTime(2003, 10, 20);
//Age
Age = d1.GetAge();
Age = d2.GetAge();
//positive
years = d1.DiffYears(d2);
Months = d1.DiffMonths(d2);
//negative
years = d2.DiffYears(d1);
Months = d2.DiffMonths(d1);
//Or
Months = Ext.DiffMonths(d1, d2);
years = Ext.DiffYears(d1, d2);
Мое понимание общей разницы месяцев между двумя датами имеет интегральную и дробную часть (дата имеет значение).
Неотъемлемая часть - разница в полных месяцах.
дробная часть для меня - это разница в% дня (до полных дней месяца) между началом и окончанием месяца.
public static class DateTimeExtensions
{
public static double TotalMonthsDifference(this DateTime from, DateTime to)
{
//Compute full months difference between dates
var fullMonthsDiff = (to.Year - from.Year)*12 + to.Month - from.Month;
//Compute difference between the % of day to full days of each month
var fractionMonthsDiff = ((double)(to.Day-1) / (DateTime.DaysInMonth(to.Year, to.Month)-1)) -
((double)(from.Day-1)/ (DateTime.DaysInMonth(from.Year, from.Month)-1));
return fullMonthsDiff + fractionMonthsDiff;
}
}
С помощью этого расширения это результаты:
2/29/2000 TotalMonthsDifference 2/28/2001 => 12
2/28/2000 TotalMonthsDifference 2/28/2001 => 12.035714285714286
01/01/2000 TotalMonthsDifference 01/16/2000 => 0.5
01/31/2000 TotalMonthsDifference 01/01/2000 => -1.0
01/31/2000 TotalMonthsDifference 02/29/2000 => 1.0
01/31/2000 TotalMonthsDifference 02/28/2000 => 0.9642857142857143
01/31/2001 TotalMonthsDifference 02/28/2001 => 1.0
Я написал функцию, чтобы выполнить это, потому что другие способы не работали для меня.
public string getEndDate (DateTime startDate,decimal monthCount)
{
int y = startDate.Year;
int m = startDate.Month;
for (decimal i = monthCount; i > 1; i--)
{
m++;
if (m == 12)
{ y++;
m = 1;
}
}
return string.Format("{0}-{1}-{2}", y.ToString(), m.ToString(), startDate.Day.ToString());
}
Есть 3 случая: в том же году, в предыдущем году и в другие годы.
Если день месяца не имеет значения ...
public int GetTotalNumberOfMonths(DateTime start, DateTime end)
{
// work with dates in the right order
if (start > end)
{
var swapper = start;
start = end;
end = swapper;
}
switch (end.Year - start.Year)
{
case 0: // Same year
return end.Month - start.Month;
case 1: // last year
return (12 - start.Month) + end.Month;
default:
return 12 * (3 - (end.Year - start.Year)) + (12 - start.Month) + end.Month;
}
}
(date1.Year - date2.Year) * 12 + date1.Month - date2.Month + (date1.Day >= date2.Day ? 0 : -1)
– DrunkCoder 22 November 2012 в 00:04