在我的应用程序中,用户输入两个日期。计划的开始日期和计划的结束日期。我们必须采用这些日期,并根据差异填充4个字段。
所以,让我们说他选择2010年1月1日作为开始,2011年3月2日作为结束,我们需要最终:
年:1 月份:2 周:0 第1天
意味着总持续时间为1年,2个月和1天。
有没有一种标准的方法可以做到这一点?或者我是否需要编写一个具有很多非常棘手的逻辑的方法来解决它?我希望我很幸运,并且会有一个date-diff类型.Net类可用。
答案 0 :(得分:6)
这是一个完整的方法,不包括数周,但可以相对简单地添加。这是一个有点复杂的问题(在stackoverflow上以多种方式提出问题,并且在很多方面都回答得很差),但是可以回答的问题。 TimeSpan对象为我们提供了我们需要的部分内容,但只能使用几天。我已经针对这种方法编写了大量测试,如果你发现了漏洞,请发表评论。
这将做的是比较2个日期,获取年,月,日,小时和分钟。 (例如某些事件发生在1年,6个月,3天,4小时和7分钟前)
因为这个问题已被提出并试图多次回答,我不确定这是否会引起注意,但如果是这样,它应该提供价值。
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;
}
答案 1 :(得分:4)
我认为TimeSpan正是您所寻找的,但它不需要数年或数月,因为它们的长度各不相同。
以下示例来自上述链接;
// 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
答案 2 :(得分:4)
您可以使用this免费库的 DateDiff 类:
// ----------------------------------------------------------------------
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
答案 3 :(得分:1)
调查C#TimeSpan结构。它没有几个月或几年,但它确实需要几天。这使事情变得更容易。
答案 4 :(得分:1)
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;
}
}
答案 5 :(得分:1)
我也需要这个,但就我而言,没有周数部分(所以只有几年,几个月和几天)。鉴于此,这就是我所做的:
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));
如果您想更动态地展示它,您也可以使用以下代码:
//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);
答案 6 :(得分:1)
这应该可以。关键是如果给定的 2 个日期之间有奇数个闰日,则将天数减少 1。
/// <summary>
/// //Assume DateTime dt1 < DateTime dt2, print out difference between dt1 to dt2 in years, months, weeks and days
/// </summary>
/// <param name="dt1"></param>
/// <param name="dt2"></param>
static void DateDiff(DateTime dt1, DateTime dt2)
{
DateTime zeroTime = new DateTime(1, 1, 1);
int leapDaysInBetween = CountLeapDays(dt1, dt2);
TimeSpan span = dt2 - dt1;
int years = (zeroTime + span).Year - 1;
int months = (zeroTime + span).Month - 1;
int days = (zeroTime + span).Day - (leapDaysInBetween % 2 == 1 ? 1 : 0);
int weeks = days / 7;
int remainingdays = days % 7;
Console.WriteLine(String.Format("\nThe difference between date {0} and date {1} is: \n\t {2} year(s), {3} month(s), and {4} day(s).", dt1, dt2, years, months, days));
Console.WriteLine(String.Format("\nThe difference between date {0} and date {1} is: \n\t {2} year(s), {3} month(s), {4} week(s) and {5} day(s).", dt1, dt2, years, months, weeks, remainingdays));
}
private static int CountLeapDays(DateTime dt1, DateTime dt2)
{
int leapDaysInBetween = 0;
int year1 = dt1.Year, year2 = dt2.Year;
DateTime dateValue;
for (int i = year1; i <= year2; i++)
{
if (DateTime.TryParse("02/29/" + i.ToString(), out dateValue))
{
if (dateValue >= dt1 && dateValue <= dt2)
leapDaysInBetween++;
}
}
return leapDaysInBetween;
}
已运行这些测试:
static void Main(string[] args)
{
DateDiff(new DateTime(2010, 1, 1), new DateTime(2012, 2, 9));
DateDiff(new DateTime(2010, 1, 1), new DateTime(2012, 4, 9));
DateDiff(new DateTime(2010, 1, 1), new DateTime(2020, 2, 9));
DateDiff(new DateTime(2010, 1, 1), new DateTime(2020, 4, 9));
DateDiff(new DateTime(2020, 2, 29), new DateTime(2021, 2, 28));
DateDiff(new DateTime(2019, 2, 28), new DateTime(2021, 2, 28));
}
这些是打印输出:
日期 1/1/2010 12:00:00 AM 和日期 4/9/2012 12:00:00 AM 之间的差异是: 2年3个月9天。
日期 1/1/2010 12:00:00 AM 和日期 4/9/2012 12:00:00 AM 之间的差异是: 2年3个月1周2天。
日期 1/1/2010 12:00:00 AM 和日期 2/9/2020 12:00:00 AM 之间的差异是: 10 年 1 个月 9 天。
日期 1/1/2010 12:00:00 AM 和日期 2/9/2020 12:00:00 AM 之间的差异是: 10年1个月1周2天。
日期 1/1/2010 12:00:00 AM 和日期 4/9/2020 12:00:00 AM 之间的差异是: 10年3个月9天。
日期 1/1/2010 12:00:00 AM 和日期 4/9/2020 12:00:00 AM 之间的差异是: 10年3个月1周2天。
日期 2/29/2020 12:00:00 AM 和日期 2/28/2021 12:00:00 AM 之间的差异是: 1 年、0 个月和 0 天。
日期 2/29/2020 12:00:00 AM 和日期 2/28/2021 12:00:00 AM 之间的差异是: 1 年、0 个月、0 周和 0 天。
日期 2/28/2019 12:00:00 AM 和日期 2/28/2021 12:00:00 AM 之间的差异是: 2年0个月1天。
日期 2/28/2019 12:00:00 AM 和日期 2/28/2021 12:00:00 AM 之间的差异是: 2年0个月0周1天。
答案 7 :(得分:0)
我创建了这个用于返回两个日期之间的年,月和日的差异。
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;
}
答案 8 :(得分:0)
如果您首先计算总月份数和总天数,逻辑不会过于复杂。然后很容易用除法和模做一些整数数学。
DateTime start_date = new DateTime(2010, 1, 1);
DateTime end_date = new DateTime(2011, 3, 2);
int diff_years = end_date.Year - start_date.Year;
int diff_months = end_date.Month - start_date.Month;
int total_months = 12 * diff_years + diff_months;
DateTime near_end_date = start_date.AddMonths(total_months);
int total_days = (int)end_date.Subtract(near_end_date).TotalDays;
int years = total_months / 12;
int months = total_months % 12;
int weeks = total_days / 7;
int days = total_days % 7;
Console.WriteLine($"Years: {years} Months: {months} Weeks: {weeks} Days: {days}");
这如预期的那样给出了 Years: 1 Months: 2 Weeks: 0 Days: 1
。
答案 9 :(得分:0)
这是我刚刚构建的转换器。我没有尝试过上述所有解决方案,但我尝试过的所有解决方案仍然以某种方式略微偏离。这考虑了年、闰年、月、周、天等,然后获取最后 YM 或 MW 或 WD 或 DH 的两个最有用的值。这很简单,但我的项目需要它,也许对未来的人有帮助。当然,如果这出于某种原因或其他原因不好,我相信你们都会告诉我。
DateTime beforeDate = topic.lastActive.ToLocalTime();
DateTime futureDate = DateTime.Now.ToLocalTime();
int minutes = 0;
int hours = 0;
int days = 0;
int weeks = 0;
int months = 0;
int years = 0;
Dictionary<int, int> dictMonths = new Dictionary<int, int> { };
dictMonths.Add(1, 31);
if (DateTime.IsLeapYear(futureDate.Year))
dictMonths.Add(2, 29);
else
dictMonths.Add(2, 28);
dictMonths.Add(3, 31);
dictMonths.Add(4, 30);
dictMonths.Add(5, 31);
dictMonths.Add(6, 30);
dictMonths.Add(7, 31);
dictMonths.Add(8, 31);
dictMonths.Add(9, 30);
dictMonths.Add(10, 31);
dictMonths.Add(11, 30);
dictMonths.Add(12, 31);
//Time difference between dates
TimeSpan span = futureDate - beforeDate;
hours = span.Hours;
minutes = span.Minutes;
//Days total
days = span.Days;
//Find how many years
DateTime zeroTime = new DateTime(1, 1, 1);
// Because we start at year 1 for the Gregorian
// calendar, we must subtract a year here.
years = (zeroTime + span).Year - 1;
//find difference of days of years already found
int startYear = futureDate.Year - years;
for (int i = 0; i < years; i++)
{
if (DateTime.IsLeapYear(startYear))
days -= 366;
else
days -= 365;
startYear++;
}
//Find months by multiplying months in year by difference of datetime years then add difference of current year months
months = 12 * (futureDate.Year - beforeDate.Year) + (futureDate.Month - beforeDate.Month);
//month may need to be decremented because the above calculates the ceiling of the months, not the floor.
//to do so we increase before by the same number of months and compare.
//(500ms fudge factor because datetimes are not precise enough to compare exactly)
if (futureDate.CompareTo(beforeDate.AddMonths(months).AddMilliseconds(-500)) <= 0)
{
--months;
}
//subtract months from how many years we have already accumulated
months -= (12 * years);
//find how many days by compared to our month dictionary
int startMonth = beforeDate.Month;
for (int i = 0; i < months; i++)
{
//check if faulty leap year
if (startMonth == 2 && (months - 1 > 10))
days -= 28;
else
days -= dictMonths[startMonth];
startMonth++;
if (startMonth > 12)
{
startMonth = 1;
}
}
//Find if any weeks are within our now total days
weeks = days / 7;
if (weeks > 0)
{
//remainder is days left
days = days % 7;
}
Console.WriteLine(years + " " + months + " " + weeks + " " + days + " " + span.Hours + " " + span.Minutes);
if (years > 0)
{
if (years > 1 && months > 1)
return $"Latest Reply: {years} years, {months} months ago.";
else if (years > 1 && months == 0)
return $"Latest Reply: {years} years ago.";
else if (years == 1 && months == 0)
return $"Latest Reply: {years} year ago.";
else if (years > 1)
return $"Latest Reply: {years} years, {months} month ago.";
else if (months > 1)
return $"Latest Reply: {years} year, {months} months ago.";
else
return $"Latest Reply: {years} year, {months} month ago.";
}
else if (months > 0)
{
if (months > 1 && weeks > 1)
return $"Latest Reply: {months} months, {weeks} weeks ago.";
else if (months > 1 && weeks == 0)
return $"Latest Reply: {months} months ago.";
else if (months == 1 && weeks == 0)
return $"Latest Reply: {months} month ago.";
else if (months > 1)
return $"Latest Reply: {months} months, {weeks} week ago.";
else if (weeks > 1)
return $"Latest Reply: {months} month, {weeks} weeks ago.";
else
return $"Latest Reply: {months} month, {weeks} week ago.";
}
else if (weeks > 0)
{
if (weeks > 1 && days > 1)
return $"Latest Reply: {weeks} weeks, {days} days ago.";
else if (weeks > 1 && days == 0)
return $"Latest Reply: {weeks} weeks ago.";
else if (weeks == 1 && days == 0)
return $"Latest Reply: {weeks} week ago.";
else if (weeks > 1)
return $"Latest Reply: {weeks} weeks, {days} day ago.";
else if (days > 1)
return $"Latest Reply: {weeks} week, {days} days ago.";
else
return $"Latest Reply: {weeks} week, {days} day ago.";
}
else if (days > 0)
{
if (days > 1 && hours > 1)
return $"Latest Reply: {days} days, {hours} hours ago.";
else if (days > 1 && hours == 0)
return $"Latest Reply: {days} days ago.";
else if (days == 1 && hours == 0)
return $"Latest Reply: {days} day ago.";
else if (days > 1)
return $"Latest Reply: {days} days, {hours} hour ago.";
else if (hours > 1)
return $"Latest Reply: {days} day, {hours} hours ago.";
else
return $"Latest Reply: {days} day, {hours} hour ago.";
}
else if (hours > 0)
{
if (hours > 1 && minutes > 1)
return $"Latest Reply: {hours} hours, {minutes} minutes ago.";
else if (hours > 1 && minutes == 0)
return $"Latest Reply: {hours} hours ago.";
else if (hours == 1 && minutes == 0)
return $"Latest Reply: {hours} hour ago.";
else if (hours > 1)
return $"Latest Reply: {hours} hours, {minutes} minute ago.";
else if (minutes > 1)
return $"Latest Reply: {hours} hour, {minutes} minutes ago.";
else
return $"Latest Reply: {hours} hour, {minutes} minute ago.";
}
else if (minutes > 0)
{
if (minutes > 1)
return $"Latest Reply: {minutes} minutes ago.";
else
return $"Latest Reply: {minutes} minute ago.";
}
else
{
return $"Latest Reply: Just now.";
}
答案 10 :(得分:0)
这是一个很老的问题,但仍有时间试一试。
重要的是要考虑到月份有不同的天数。
public static (int, int, int) GetYearsMonthsDaysDifference(DateTime date1, DateTime date2)
{
DateTime startDate = date1;
DateTime endDate = date2;
if (date1 > date2)
{
startDate = date2;
endDate = date1;
}
var months = (endDate.Month + (12 - startDate.Month)) - (endDate.Day < startDate.Day ? 1 : 0);
var years = (endDate.Year - startDate.Year - (months < 12 ? 1 : 0));
months -= (months >= 12 ? 12 : 0);
var days = endDate.DayOfYear - startDate.AddYears(years).AddMonths(months).DayOfYear;
return (years, months, days);
}