Calculate Years, Months, weeks and Days
在我的应用程序中,用户输入两个日期。计划开始日期和计划结束日期。我们必须获取这些日期,并根据差异填充4个字段。
所以,假设他选择2010年1月1日作为开始,2011年3月2日作为结束,我们需要以:
年份:1月份:2周:0第1天
这意味着总持续时间是1年、2个月和1天。
有没有一个标准的方法来做到这一点?或者我需要写一个有很多非常复杂逻辑的方法来解决这个问题?我希望我能走运,会有一个日期差异类型的.NET类可用。
这里有一个完整的方法,不包括星期,但可以相对简单地添加。这是一个有点复杂的问题(在stackoverflow上以多种方式提问,并以多种方式回答得很差),但回答的也不尽相同。TimeSpan对象为我们提供了所需的部分内容,但只在几天内有效。我已经针对这个方法编写了大量的测试,如果你发现了一个漏洞,请发表评论。
这将要做的是比较两个日期,分别是年、月、日、小时和分钟。(例如,1年、6个月、3天、4小时和7分钟前发生了一些事件)
因为这个问题已经被问过很多次,并且试图回答过很多次,我不确定这是否会被注意到,但是如果是这样的话,它应该提供价值。
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 | public static void TimeSpanToDateParts(DateTime d1, DateTime d2, out int years, out int months, out int days, out int hours, out int minutes) { if (d1 < d2) { var d3 = d2; d2 = d1; d1 = d3; } var span = d1 - d2; months = 12 * (d1.Year - d2.Year) + (d1.Month - d2.Month); //month may need to be decremented because the above calculates the ceiling of the months, not the floor. //to do so we increase d2 by the same number of months and compare. //(500ms fudge factor because datetimes are not precise enough to compare exactly) if (d1.CompareTo(d2.AddMonths(months).AddMilliseconds(-500)) <= 0) { --months; } years = months / 12; months -= years * 12; if (months == 0 && years == 0) { days = span.Days; } else { var md1 = new DateTime(d1.Year, d1.Month, d1.Day); // Fixed to use d2.Day instead of d1.Day var md2 = new DateTime(d2.Year, d2.Month, d2.Day); var mDays = (int) (md1 - md2).TotalDays; if (mDays > span.Days) { mDays = (int)(md1.AddMonths(-1) - md2).TotalDays; } days = span.Days - mDays; } hours = span.Hours; minutes = span.Minutes; } |
您可以使用此免费库的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 |
我认为时间跨度是你想要的,但它不适用于年或月,因为它们的长度不同。
下面的例子来自上面的链接;
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 | // Define two dates. DateTime date1 = new DateTime(2010, 1, 1, 8, 0, 15); DateTime date2 = new DateTime(2010, 8, 18, 13, 30, 30); // Calculate the interval between the two dates. TimeSpan interval = date2 - date1; Console.WriteLine("{0} - {1} = {2}", date2, date1, interval.ToString()); // Display individual properties of the resulting TimeSpan object. Console.WriteLine(" {0,-35} {1,20}","Value of Days Component:", interval.Days); Console.WriteLine(" {0,-35} {1,20}","Total Number of Days:", interval.TotalDays); Console.WriteLine(" {0,-35} {1,20}","Value of Hours Component:", interval.Hours); Console.WriteLine(" {0,-35} {1,20}","Total Number of Hours:", interval.TotalHours); Console.WriteLine(" {0,-35} {1,20}","Value of Minutes Component:", interval.Minutes); Console.WriteLine(" {0,-35} {1,20}","Total Number of Minutes:", interval.TotalMinutes); Console.WriteLine(" {0,-35} {1,20:N0}","Value of Seconds Component:", interval.Seconds); Console.WriteLine(" {0,-35} {1,20:N0}","Total Number of Seconds:", interval.TotalSeconds); Console.WriteLine(" {0,-35} {1,20:N0}","Value of Milliseconds Component:", interval.Milliseconds); Console.WriteLine(" {0,-35} {1,20:N0}","Total Number of Milliseconds:", interval.TotalMilliseconds); Console.WriteLine(" {0,-35} {1,20:N0}","Ticks:", interval.Ticks); // the example displays the following output: // 8/18/2010 1:30:30 PM - 1/1/2010 8:00:15 AM = 229.05:30:15 // Value of Days Component: 229 // Total Number of Days: 229.229340277778 // Value of Hours Component: 5 // Total Number of Hours: 5501.50416666667 // Value of Minutes Component: 30 // Total Number of Minutes: 330090.25 // Value of Seconds Component: 15 // Total Number of Seconds: 19,805,415 // Value of Milliseconds Component: 0 // Total Number of Milliseconds: 19,805,415,000 // Ticks: 198,054,150,000,000 |
我也需要这个,但在我的情况下,没有周部分(所以只有年,月和天)。鉴于此,我做的是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | DateTime startDate = DateTime.ParseExact (start,"dd/MM/yyyy",CultureInfo.InvariantCulture); DateTime endDate = DateTime.ParseExact (end,"dd/MM/yyyy",CultureInfo.InvariantCulture); int days=0; int months = 0; int years = 0; //calculate days if (endDate.Day >= startDate.Day) { days = endDate.Day - startDate.Day; } else { var tempDate = endDate.AddMonths (-1); int daysInMonth = DateTime.DaysInMonth (tempDate.Year, tempDate.Month); days = daysInMonth - (startDate.Day - endDate.Day); months--; } //calculate months if (endDate.Month >= startDate.Month) { months+=endDate.Month - startDate.Month; } else { months+= 12 - (startDate.Month - endDate.Month); years--; } //calculate years years+=endDate.Year - startDate.Year; Debug.WriteLine (string.Format("{0} years, {1} months, {2} days",years,months,days)); |
如果要更动态地显示此代码,还可以使用以下代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | //build the string var result =""; if (years!=0){ result = years == 1 ? years +" year" : years +" years"; } if (months != 0) { if (result !="") { result +=","; } result += months == 1 ? months +" month" : months +" months"; } if (days != 0) { if (result !="") { result +=","; } result += days == 1 ? days +" day" : days +" days"; } Debug.WriteLine (result); |
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 | public partial class Age1 : System.Web.UI.Page { private int Years; private int Months; private int Days; DateTime Cday; DateTime Bday; protected void Page_Load(object sender, EventArgs e) { txtCurrentDate.Enabled = false; txtCurrentDate.Text = DateTime.Now.ToString("g"); Cday = Convert.ToDateTime(txtCurrentDate.Text); } protected void Button1_Click(object sender, EventArgs e) { Bday = Convert.ToDateTime(txtBirthdate.Text); AgeCaluclation(Bday, Cday); txtBirthdate.Text =""; txtCurrentDate.Text =""; lblAge.Text = this.Years+" Years"+this.Months+" Months" +this.Days+"Days"; } private Age1 AgeCaluclation(DateTime Bday, DateTime Cday) { if ((Cday.Year - Bday.Year) > 0 || (((Cday.Year - Bday.Year) == 0) && ((Bday.Month < Cday.Month) || ((Bday.Month == Cday.Month) && (Bday.Day <= Cday.Day))))) { int DaysInBdayMonth = DateTime.DaysInMonth(Bday.Year, Bday.Month); int DaysRemain = Cday.Day + (DaysInBdayMonth - Bday.Day); if(Cday.Month > Bday.Month) { this.Years = Cday.Year - Bday.Year; this.Months = Cday.Month - (Bday.Month + 1) + Math.Abs(DaysRemain / DaysInBdayMonth); this.Days = (DaysRemain % DaysInBdayMonth + DaysInBdayMonth) % DaysInBdayMonth; } else if (Cday.Month == Bday.Month) { if (Cday.Day >= Bday.Day) { this.Years = Cday.Year - Bday.Year; this.Months = 0; this.Days = Cday.Day - Bday.Day; } else { this.Years = (Cday.Year - 1) - Bday.Year; this.Months = 11; this.Days = DateTime.DaysInMonth(Bday.Year, Bday.Month) - (Bday.Day - Cday.Day); } } else { this.Years = (Cday.Year - 1) - Bday.Year; this.Months = Cday.Month + (11 - Bday.Month) + Math.Abs(DaysRemain / DaysInBdayMonth); this.Days = (DaysRemain % DaysInBdayMonth + DaysInBdayMonth) % DaysInBdayMonth; } } else { throw new ArgumentException("Birthday date must be earlier than current date"); } return this; } } |
研究c时间跨度结构。它不需要几个月或几年,但需要几天。这使事情变得更容易。
我创建这一个是为了返回两个日期之间的年、月和日的差异。
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 | public static Dictionary<string, int> TimeSpanToDateParts(DateTime fromDate,DateTime toDate) { int years; int months; int days; Dictionary<string, int> dateParts = new Dictionary<string, int>(); if (toDate < fromDate) { return TimeSpanToDateParts(toDate,fromDate); } var span = toDate - fromDate; months = 12 * (toDate.Year - fromDate.Year) + (toDate.Month - fromDate.Month); if (toDate.CompareTo(fromDate.AddMonths(months).AddMilliseconds(-500)) <= 0) { --months; } years = months / 12; months -= years * 12; if (months == 0 && years == 0) { days = span.Days; } else { days = toDate.Day; if (fromDate.Day > toDate.Day) days = days + (DateTime.DaysInMonth(toDate.Year, toDate.Month - 1) - fromDate.Day); else days = days - fromDate.Day; } dateParts.Add("Years", years); dateParts.Add("Months", months); dateParts.Add("Days", days); return dateParts; } |