日期返回正确的月数和年数的时差

本文关键字:时差 返回 日期 | 更新日期: 2023-09-27 18:00:43

是否有任何内置函数?如何以比天数更好的方式获得tho-DateTime对象之间的差异?我的意思是大约1个月,23天。由于每个月、闰年的天数不同,我发现很难计算。感谢

日期返回正确的月数和年数的时差

看看Noda Time。一般来说,它还没有准备好生产,但相关的比特可能足以满足您当前的需求:)

请注意,TimeSpan不会执行您想要的操作,因为"1个月"可能意味着根据月份不同的天数,并且TimeSpan没有固定。

在"野田时间"中,您需要一个Period。例如:

LocalDate start = new LocalDate(2010, 4, 15);
LocalDate end = new LocalDate(2010, 6, 19);
Period period = Period.Between(start, end); // Defaults to Year/Month/Day
Console.WriteLine(period.Months); // 2
Console.WriteLine(period.Days); // 4

请注意,日期/时间运算很难。。。在某些情况下,"正确答案"并不明显。

月份可以由28天、29天、30天或31天组成;年可以是365天或366天。因此,当你试图计算月和年的完整时间单位时,会出现问题。因此,如果你可以假设一些事情,那么你可以检查

简单的减法就能完成任务:

int months = departure.Months - arrival.Months;
int years = departure.Years - arrival.Years;
//in case multiple years have elapsed .
int months += years * 12;

很明显,当谈到天数时,你需要做一些数学运算,如果你不在乎精度,如果天数差是负数,你就需要从这个月减去一。


然后你可以使用TimeSpan来获得更高的精度,也就是经过的时间。

//Microsoft Documentation Example:
DateTime departure = new DateTime(2010, 6, 12, 18, 32, 0);
DateTime arrival = new DateTime(2010, 6, 13, 22, 47, 0);
TimeSpan travelTime = arrival - departure;  
Console.WriteLine("{0} - {1} = {2}", arrival, departure, travelTime);   
// The example displays the following output:
//       6/13/2010 10:47:00 PM - 6/12/2010 6:32:00 PM = 1.04:15:00

这种问题很难为日历日期指定。看看这里,可以很好地计算出如何以年为单位计算一个人的年龄。

在C#中计算年龄

复杂性来自于边缘案例。显然,1月31日是12月31日之后的一个月。但是,2月28日是1月31日之后的一个月吗?在正常年份?闰年?在编写代码之前,您需要指定这些类型的案例。

生日算法采用四舍五入和递增策略。考虑到你对上一段中问题的回答,这也适用于月份差异。

以下是我刚刚编写的一些代码,用于计算年、月和天的差异。它在公共领域。

    public sealed class DateDifference {
            int years;
            public int Years {
                get { return years; }
            }
            int months;
            public int Months {
                get { return months; }
            }
            int days;
            public int Days {
                get { return days; }
            }
            public override string ToString()
            {
                return string.Format("[DateDifference Years={0}, Months={1}, Days={2}]", years, months, days);
            }

            public DateDifference(DateTime earlier, DateTime later){
                if(later<earlier)
                    throw new ArgumentException("later is earlier than 'earlier'.");
                bool isleapday=(earlier.Month==2 && earlier.Day==29);
                DateTime tmp=isleapday ? new DateTime(earlier.Year,2,28) : earlier;
                while(true){
                    try {
                        tmp=tmp.AddYears(1);
                        if(isleapday && DateTime.IsLeapYear(tmp.Year))
                            tmp=new DateTime(tmp.Year,2,29);
                    } catch(ArgumentOutOfRangeException){
                        break;
                    }
                    if(tmp<=later){
                        years++;
                        earlier=tmp;
                    } else {
                        break;
                    }
                }
                // Add months
                tmp=earlier;
                while(true){
                    try {
                        tmp=tmp.AddMonths(1);
                    if(isleapday && tmp.Day!=29 && tmp.Month!=2)
                        tmp=new DateTime(tmp.Year,tmp.Month,29);
                    } catch(ArgumentOutOfRangeException){
                        break;
                    }
                    if(tmp<=later){
                        months++;
                        earlier=tmp;
                    } else {
                        break;
                    }
                }
                tmp=earlier;
                while(true){
                    try {
                        tmp=tmp.AddDays(1);
                    } catch(ArgumentOutOfRangeException){
                        break;
                    }
                    if(tmp<=later){
                        days++;
                        earlier=tmp;
                    } else {
                        break;
                    }
                }
            }
        }

示例:

var dd=new DateDifference(new DateTime(2010,6,29),new DateTime(2012,2,29));
Console.WriteLine(dd.Years); // displays 1
Console.WriteLine(dd.Months); // displays 8
Console.WriteLine(dd.Days); // displays 0

您可以将时间段库的DateDiff类用于。NET:

// ----------------------------------------------------------------------
public void DateDiffSample()
{
  DateTime date1 = new DateTime( 2009, 11, 8, 7, 13, 59 );
  Console.WriteLine( "Date1: {0}", date1 );
  // > Date1: 08.11.2009 07:13:59
  DateTime date2 = new DateTime( 2011, 3, 20, 19, 55, 28 );
  Console.WriteLine( "Date2: {0}", date2 );
  // > Date2: 20.03.2011 19:55:28
  DateDiff dateDiff = new DateDiff( date1, date2 );
  // differences
  Console.WriteLine( "DateDiff.Years: {0}", dateDiff.Years );
  // > DateDiff.Years: 1
  Console.WriteLine( "DateDiff.Quarters: {0}", dateDiff.Quarters );
  // > DateDiff.Quarters: 5
  Console.WriteLine( "DateDiff.Months: {0}", dateDiff.Months );
  // > DateDiff.Months: 16
  Console.WriteLine( "DateDiff.Weeks: {0}", dateDiff.Weeks );
  // > DateDiff.Weeks: 70
  Console.WriteLine( "DateDiff.Days: {0}", dateDiff.Days );
  // > DateDiff.Days: 497
  Console.WriteLine( "DateDiff.Weekdays: {0}", dateDiff.Weekdays );
  // > DateDiff.Weekdays: 71
  Console.WriteLine( "DateDiff.Hours: {0}", dateDiff.Hours );
  // > DateDiff.Hours: 11940
  Console.WriteLine( "DateDiff.Minutes: {0}", dateDiff.Minutes );
  // > DateDiff.Minutes: 716441
  Console.WriteLine( "DateDiff.Seconds: {0}", dateDiff.Seconds );
  // > DateDiff.Seconds: 42986489
  // elapsed
  Console.WriteLine( "DateDiff.ElapsedYears: {0}", dateDiff.ElapsedYears );
  // > DateDiff.ElapsedYears: 1
  Console.WriteLine( "DateDiff.ElapsedMonths: {0}", dateDiff.ElapsedMonths );
  // > DateDiff.ElapsedMonths: 4
  Console.WriteLine( "DateDiff.ElapsedDays: {0}", dateDiff.ElapsedDays );
  // > DateDiff.ElapsedDays: 12
  Console.WriteLine( "DateDiff.ElapsedHours: {0}", dateDiff.ElapsedHours );
  // > DateDiff.ElapsedHours: 12
  Console.WriteLine( "DateDiff.ElapsedMinutes: {0}", dateDiff.ElapsedMinutes );
  // > DateDiff.ElapsedMinutes: 41
  Console.WriteLine( "DateDiff.ElapsedSeconds: {0}", dateDiff.ElapsedSeconds );
  // > DateDiff.ElapsedSeconds: 29
} // DateDiffSample

试试这个

    public string YearsMonthsDaysDiff(DateTime dateFrom, DateTime dateTo)
    {
        Int32 mD = DateTime.DaysInMonth(dateTo.Year, dateTo.AddMonths(-1).Month); //first check out days in month before dateTo month
        Int32 D1 = dateFrom.Day;
        Int32 M1 = dateFrom.Month;
        Int32 Y1 = dateFrom.Year;
        Int32 D2 = dateTo.Day;
        Int32 M2 = dateTo.Month;
        Int32 Y2 = dateTo.Year;
        // Substract each datetime components accordingly
        D2 -= D1;
        M2 -= M1;
        Y2 -= Y1;
        if (D2 < 0)
        {
            D2 += mD;// D2 is less then D1, then add mD
            M2 -= 1; // but, substract 1 from M2 
        }
        if (M2 < 0)
        {
            M2 += 12; // if M2 is less then M1, then add with 12
            Y2 -= 1; // but substract 1 from Y2 
        }
        return Y2.ToString("## years ") + M2.ToString("##  months ") + D2.ToString("## days");
    }

它对我来说很好

这里有一个类,允许您查询一对DateTimes差异的各种属性。我刚刚把它搞起来,并将其发布到公共领域。随意使用,但使用风险自负。

public static class DateCalcs
{
    /// <summary>
    /// returns the integer number of years between start and finish
    /// </summary>
    /// <param name="start">Start DateTime</param>
    /// <param name="finish">FinishDateTime</param>
    /// <returns></returns>
    public static int YearDiff(DateTime start, DateTime finish)
    {
        DateTime _start, _finish;
        bool _negate = (finish < start);
        if(_negate)
        {
            _start = finish;
            _finish = start;
        }
        else
        {
            _start = start;
            _finish = finish;
        }
        int _diff = 0;
        while(_start.AddYears(1) < _finish)
        {
            _diff++;
            _start = _start.AddYears(1);
        }
        if(_negate)
        {
            _diff = _diff * (-1);
        }
        return _diff;
    }
    /// <summary>
    /// returns the integer number of months between start and finish
    /// </summary>
    /// <param name="start">Start DateTime</param>
    /// <param name="finish">Finish DateTime</param>
    /// <returns></returns>
    public static int MonthDiff(DateTime start, DateTime finish)
    {
        DateTime _start, _finish;
        bool _negate = (finish < start);
        if (_negate)
        {
            _start = finish;
            _finish = start;
        }
        else
        {
            _start = start;
            _finish = finish;
        }
        int _diff = 0;
        while (_start.AddMonths(1) < _finish)
        {
            _diff++;
            _start = _start.AddMonths(1);
        }
        if (_negate)
        {
            _diff = _diff * (-1);
        }
        return _diff;
    }
    /// <summary>
    /// returns the integer number of days between start and finish
    /// </summary>
    /// <param name="start">start DateTime</param>
    /// <param name="finish">finish DateTime</param>
    /// <returns></returns>
    public static int DayDiff(DateTime start, DateTime finish)
    {
        var _diff = finish - start;
        return (int)_diff.TotalDays;
    }
    /// <summary>
    /// returns the integer number of hours between start and finish
    /// </summary>
    /// <param name="start">start DateTime</param>
    /// <param name="finish">finish DateTime</param>
    /// <returns></returns>
    public static int HourDiff(DateTime start, DateTime finish)
    {
        var _diff = finish - start;
        return(int)_diff.TotalHours;
    }
    /// <summary>
    /// returns the integer number of minutes between start and finish
    /// </summary>
    /// <param name="start">start DateTime</param>
    /// <param name="finish">finish DateTime</param>
    /// <returns></returns>
    public static int MinuteDiff(DateTime start, DateTime finish)
    {
        var _diff = finish - start;
        return (int)_diff.TotalMinutes;
    }
    /// <summary>
    /// returns the integer number of seconds between start and finish
    /// </summary>
    /// <param name="start">start DateTime</param>
    /// <param name="finish">finish DateTime</param>
    /// <returns></returns>
    public static int SecondDiff(DateTime start, DateTime finish)
    {
        var _diff = finish - start;
        return (int)_diff.TotalSeconds;
    }
    /// <summary>
    /// returns the integer number of milliseconds between start and finish
    /// </summary>
    /// <param name="start">start DateTime</param>
    /// <param name="finish">finish DateTime</param>
    /// <returns></returns>
    public static int MilliSecondDiff(DateTime start, DateTime finish)
    {
        var _diff = finish - start;
        return (int)_diff.TotalMilliseconds;
    }
    /// <summary>
    /// returns the integer remaining number of months between two DateTimes 
    /// after the year difference has been removed
    /// </summary>
    /// <param name="start">start DateTime</param>
    /// <param name="finish">finish DateTime</param>
    /// <returns></returns>
    public static int MonthPartDiff(DateTime start, DateTime finish)
    {
        return MonthDiff(start.AddYears(YearDiff(start, finish)), finish);
    }
    /// <summary>
    /// returns the integer remaining number of days between two DateTimes 
    /// after the year difference and the month difference has been removed
    /// </summary>
    /// <param name="start"></param>
    /// <param name="finish"></param>
    /// <returns></returns>
    public static int DayPartDiff(DateTime start, DateTime finish)
    {
        return DayDiff(start.AddMonths(MonthDiff(start, finish)), finish);
    }
    /// <summary>
    /// returns the integer remaining number of hours between two DateTimes 
    /// after the year, month and day difference has been removed
    /// </summary>
    /// <param name="start"></param>
    /// <param name="finish"></param>
    /// <returns></returns>
    public static int HourPartDiff(DateTime start, DateTime finish)
    {
        return (finish-start).Hours;
    }
    /// <summary>
    /// returns the integer remaining number of minutes between two DateTimes 
    /// after the year, month, day and hour difference has been removed
    /// </summary>
    /// <param name="start"></param>
    /// <param name="finish"></param>
    /// <returns></returns>
    public static int MinutePartDiff(DateTime start, DateTime finish)
    {
        return (finish-start).Minutes;
    }
    /// <summary>
    /// returns the integer remaining number of seconds between two DateTimes 
    /// after the year, month, day, hour and minute difference has been removed
    /// </summary>
    /// <param name="start"></param>
    /// <param name="finish"></param>
    /// <returns></returns>
    public static int SecondPartDiff(DateTime start, DateTime finish)
    {
        return (finish - start).Seconds;
    }
    /// <summary>
    /// returns the integer remaining number of milliseconds between two DateTimes 
    /// after the year, month, day, hour, minute and second difference has been removed
    /// </summary>
    /// <param name="start"></param>
    /// <param name="finish"></param>
    /// <returns></returns>
    public static int MilliSecondPartDiff(DateTime start, DateTime finish)
    {
        return (finish - start).Milliseconds;
    }
}

所以你可以这样称呼它:

var finish = DateTime.Now;
var start = new DateTime(1967, 7, 3);
var years = DateCalcs.YearDiff(start, finish);
Console.WriteLine ("Age in years: {0}", years);
var months = DateCalcs.MonthDiff(start, finish);
Console.WriteLine("Age in months: {0}", months);
var days = DateCalcs.DayDiff(start, finish);
Console.WriteLine("Age in days: {0}", days);
var hours = DateCalcs.HourDiff(start, finish);
Console.WriteLine("Age in hours: {0}", hours);
var minutes = DateCalcs.MinuteDiff(start, finish);
Console.WriteLine("Age in minutes: {0}", minutes);
var seconds = DateCalcs.SecondDiff(start, finish);
Console.WriteLine("Age in seconds: {0}", seconds);
var milliSeconds = DateCalcs.MilliSecondDiff(start, finish);
Console.WriteLine("Age in milliseconds: {0}", milliSeconds);
var AgeString = string.Format("{0}yr, {1}mo, {2}d, {3}h, {4}m, {5}s, {6}ms",
    DateCalcs.YearDiff(start, finish),
    DateCalcs.MonthPartDiff(start, finish),
    DateCalcs.DayPartDiff(start, finish),
    DateCalcs.HourPartDiff(start, finish),
    DateCalcs.MinutePartDiff(start, finish),
    DateCalcs.SecondPartDiff(start, finish),
    DateCalcs.MilliSecondPartDiff(start, finish)
    );
Console.WriteLine("Or {0}", AgeString);

刚刚返回

Age in years: 46
Age in months: 560
Age in days: 17073
Age in hours: 409771
Age in minutes: 24586290
Age in seconds: 1475177401
Age in milliseconds: -2147483648
Or 46yr, 8mo, 28d, 19h, 30m, 1s, 792ms