关于c#:日期时间差异正在推迟几个月甚至几年?

DateTime difference returing correct no of months and or even years?

是否有任何内置函数,我如何才能以比仅天数更好的方式获得日期时间对象之间的差异?我的意思是1个月23天。由于每个月的天数、闰年等不同,我觉得很难计算。谢谢


看看野田时间。一般来说,它还没有准备好生产,但是相关的位可以很好地满足您当前的需求:)

注意,TimeSpan不会做你想做的,因为"1个月"可以表示不同的天数,具体取决于月份,而TimeSpan没有固定。

在野田佳彦时期,你需要一个Period。例如:

2

请注意,日期/时间算术很难…在某些情况下,"正确的答案"根本不明显。


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


简单的减法可以做到:

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

很明显,当涉及到天数时,你需要做一些数学计算,如果你不关心精度,如果日差是负数,你需要从月份中减去一个。

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

1
2
3
4
5
6
7
8
9
//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


这是我刚写的一些代码,用来计算年、月和日的差异。它在公共领域。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
    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;
                    }
                }
            }
        }

例子:

1
2
3
4
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

这类问题对于日历日期来说非常难指定。看看这里如何计算一个人的年龄(以年为单位)。

以C为单位计算年龄#

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

生日算法使用向下取整和递增策略。考虑到你对上一段中的问题的回答,这同样适用于月份差异。


这是一个类,它允许您查询一对日期时间差的各种属性。我刚刚把它搅了起来,并将它发布到公共领域。照你的意愿去做,但要自担风险地使用它。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
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;
    }

}

所以你可以这样称呼它:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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);

刚刚回来的

1
2
3
4
5
6
7
8
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


试试这个

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
    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");
    }

对我来说很好


可以使用.NET时间段库的datediff类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
// ----------------------------------------------------------------------
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