C# DateTime.AddMonths仅添加月份,不添加天数
比如说,我有2010年2月28日的并使用C# DateTime.AddMonths仅添加月份,不添加天数,c#,datetime,C#,Datetime,比如说,我有2010年2月28日的并使用AddMonths(1)… 结果日期是3月28日,但不是我想要的3月31日。 有没有办法稍微调整一下,这样就可以在不添加自定义代码的情况下工作 编辑:我不需要一个月的最后一天,实际上我需要添加一个月,但是当它是一个月的最后一天时,我需要找到下个月的最后一天。否-它没有考虑到这一点。这是自定义代码的所有方式 您的代码只对月的最后一天感兴趣,还是希望代码在任何日期中添加一个月,但要考虑提供的日期何时是月的最后一天?尝试重载day属性并将其设置为32。这是用Ja
AddMonths(1)
…结果日期是3月28日,但不是我想要的3月31日。
有没有办法稍微调整一下,这样就可以在不添加自定义代码的情况下工作
编辑:我不需要一个月的最后一天,实际上我需要添加一个月,但是当它是一个月的最后一天时,我需要找到下个月的最后一天。否-它没有考虑到这一点。这是自定义代码的所有方式
您的代码只对月的最后一天感兴趣,还是希望代码在任何日期中添加一个月,但要考虑提供的日期何时是月的最后一天?尝试重载day属性并将其设置为32。这是用JavaScript实现的,我相信它会默认回到你所在月份的最后一天。我不知道你想要实现什么,但你可以加上一天,加上一个月,减去一天
DateTime nextMonth = date.AddDays(1).AddMonths(1).AddDays(-1);
编辑:
正如一位评论者指出的那样,这有时会给出错误的结果。在阅读了您更新的问题后,我认为计算您想要的日期的最简单方法是:
public static DateTime NextMonth(this DateTime date)
{
if (date.Day != DateTime.DaysInMonth(date.Year, date.Month))
return date.AddMonths(1);
else
return date.AddDays(1).AddMonths(1).AddDays(-1);
}
此扩展方法返回下个月的日期。当当前日期是该月的最后一天时,它将返回下个月的最后一天。如果您的意思是结果日期应该与该月的结束日期保持相同的距离,则您进入了自定义代码-类似(未完全测试,尤其是28/30/31个月):
我现在解决了这个问题,使用GetLastDayInCurrentMonth检查它是否是一个月的最后一天。如果是这样的话,我用
DateTime nextMonth = date.AddDays(1).AddMonths(1).AddDays(-1);
如果不是最后一天,我只使用AddMonths(1)
谢谢大家 像这样怎么样?它解决了1月30日的问题,该问题将与当前的最佳答案一起出现
if(yourDate.Day == DaysInMonth(yourDate.Year,yourDate.Month)) //check for last day
yourDate.AddDays(DateTime.DaysInMonth(yourDate.Year,(yourDate.Month+1)%12));
public static DateTime AddJustMonths(this DateTime @this, int months)
{
var firstDayOfTargetMonth = new DateTime(@this.Year, @this.Month, 1).AddMonths(months);
var lastDayofTargetMonth = DateTime.DaysInMonth(firstDayOfTargetMonth.Year, firstDayOfTargetMonth.Month);
var targetDay = @this.Day > lastDayofTargetMonth ? lastDayofTargetMonth : @this.Day;
return new DateTime(firstDayOfTargetMonth.Year, firstDayOfTargetMonth.Month, targetDay);
}
此代码将添加月数,如果当前日期是当前月份的最后一天,则将跳转到目标月份的最后一天。请注意,如果不完全定制日期,1月30日的问题基本上没有解决方案: 如果日期是唯一的状态,那么无论你如何处理从1月30日起提前一个月的跳跃,你都必须选择是将结果解释为2月的最后一天还是仅仅是当月的28日。你不能两者兼得,因为日期是你唯一的状态。没有“旗帜”告诉你二月二十八日原本是一月的最后一天 实际上,这意味着Jan30.AddMonthCustom(1).AddMonthCustom(1)!=1月30日。如果你继续宣传,那么任何30日、29日和28日最终都会在一个月的最后一天结束
public static DateTime AddMonthsCustom(this DateTime date, int months)
{
// Check if we are done quickly.
if(months == 0)
return;
// Lookup the target month and its last day.
var targetMonth = new DateTime(date.Year, date.Month, 1).AddMonths(months);
var lastDay = DateTime.DaysInMonth(targetMonth.Year, targetMonth.Month);
// If we are starting out on the last day of the current month, then jump
// to the last day of the target month.
if (date.Day == DateTime.DaysInMonth(date.Year, date.Month))
return new DateTime(targetMonth.Year, targetMonth.Month, lastDay);
// If the target month cannot accomodate the current day, jump to the
// last day of the target month.
if (date.Day > lastDay)
return new DateTime(targetMonth.Year, targetMonth.Month, lastDay);
// Simply jump to the current day in the target month.
return new DateTime(targetMonth.Year, targetMonth.Month, date.Day);
}
如果我错了,请告诉我。我真的很想解决这个问题。这个怎么样?作为一种扩展方法,它可以添加任意多个月,即
dateDue.AddSmarthMonths(6)代码>--并将1月28日之后的任何一天视为“本月的最后一天”
public static DateTime AddSmartMonths(此日期时间为d,整数为n个月)
{
int year=d.年;
整月=d.月;
int日=d日;
如果((天==30)和&(天<日期时间.DaysInMonth(年,月)))
d=d.add天(1);
如果((月==1)和&(日>28))
d=新日期时间(年、月、31);
返回d.AddMonths(n个月);
}
并概括为多个月:
public static DateTime AddMonthToEndOfMonth(DateTime date, int numberOfMonths)
{
DateTime nextMonth = date.AddMonths(numberOfMonths);
if (date.Day != DateTime.DaysInMonth(date.Year, date.Month)) //is last day in month
{
//any other day then last day
return nextMonth;
}
else
{
//if date was end of month, add remaining days
int addDays = DateTime.DaysInMonth(nextMonth.Year, nextMonth.Month) - nextMonth.Day;
return nextMonth.AddDays(addDays);
}
}
代码针对二月号、闰年和新年过渡进行了测试。所有测试都通过了
[TestMethod]
公共无效AddMonthTest_一月()
{
对于(inti=1;i你可以试试这个
private void datTimPkerFrom_ValueChanged(object sender, EventArgs e)
{
int DaysInMonth = DateTime.DaysInMonth(datTimPkerFrom.Value.Year, datTimPkerFrom.Value.Month);
if (DaysInMonth == 31)
{
datTimPkerTo.Value = datTimPkerFrom.Value.AddDays(30);
}
else if (DaysInMonth == 30)
{
datTimPkerTo.Value = datTimPkerFrom.Value.AddDays(29);
}
else if (DaysInMonth == 29)
{
datTimPkerTo.Value = datTimPkerFrom.Value.AddDays(28);
}
else
{
datTimPkerTo.Value = datTimPkerFrom.Value.AddDays(27);
}
}
rashleighp的建议几乎正确,但不适用于2016-02-29(结果应为2016-03-31)或2017-02-28(结果应为2017-03-31)增加1个月
此修改版本应适用于所有特殊情况
public static DateTime AddMonthsCustom(this DateTime source, int months)
{
var firstDayOfTargetMonth = new DateTime(source.Year, source.Month, 1).AddMonths(months);
var lastDayofSourceMonth = DateTime.DaysInMonth(source.Year, source.Month);
var lastDayofTargetMonth = DateTime.DaysInMonth(firstDayOfTargetMonth.Year, firstDayOfTargetMonth.Month);
var targetDay = source.Day > lastDayofTargetMonth ? lastDayofTargetMonth : source.Day;
if (source.Day == lastDayofSourceMonth)
targetDay = lastDayofTargetMonth;
return new DateTime(
firstDayOfTargetMonth.Year,
firstDayOfTargetMonth.Month,
targetDay,
source.Hour,
source.Minute,
source.Second,
source.Millisecond,
source.Kind);
}
以下所有NUnit测试均通过:
[TestCase("2017-01-01T01:01:01.0010000Z", "2016-12-01T01:01:01.0010000Z", 1)]
[TestCase("2017-02-01T01:01:01.0010000Z", "2016-12-01T01:01:01.0010000Z", 2)]
[TestCase("2017-03-31T01:01:01.0010000Z", "2016-12-31T01:01:01.0010000Z", 3)]
[TestCase("2016-03-28T01:01:01.0010000Z", "2016-02-28T01:01:01.0010000Z", 1)]
[TestCase("2016-03-31T01:01:01.0010000Z", "2016-02-29T01:01:01.0010000Z", 1)]
[TestCase("2017-03-31T01:01:01.0010000Z", "2017-02-28T01:01:01.0010000Z", 1)]
[TestCase("2016-02-29T01:01:01.0010000Z", "2016-01-31T01:01:01.0010000Z", 1)]
[TestCase("2017-02-28T01:01:01.0010000Z", "2017-01-31T01:01:01.0010000Z", 1)]
[TestCase("2016-12-01T01:01:01.0010000Z", "2017-01-01T01:01:01.0010000Z", -1)]
[TestCase("2016-12-01T01:01:01.0010000Z", "2017-02-01T01:01:01.0010000Z", -2)]
[TestCase("2016-12-31T01:01:01.0010000Z", "2017-03-31T01:01:01.0010000Z", -3)]
[TestCase("2016-02-28T01:01:01.0010000Z", "2016-03-28T01:01:01.0010000Z", -1)]
public void DateTimeExtensions_AddMonthsCustom(DateTime expected, DateTime dateTime, int months)
{
// Arrange
expected = expected.ToUniversalTime();
dateTime = dateTime.ToUniversalTime();
// Act
DateTime result = dateTime.AddMonthsCustom(months);
// Assert
Assert.AreEqual(expected.Kind, result.Kind);
Assert.AreEqual(expected, result);
}
这会将numMonths添加到someDate,如果someDate是月末,返回值将是月末,否则它只会添加months(numMonths)
在一行中给出下个月的最后一天:
var t1 = new DateTime(2010,2,28);
var t2 = t1.AddDays((t1.Day * -1) + 1).AddMonths(2).AddMilliseconds(-1).Date;
// t2: {31.03.2010 00:00:00}
(操作是:获取当月的第一天(=1.Feb 10),加上2个月(=1.Apr 10),减去1毫秒(=31.Mar 10),如果给定的日期是当月的最后一天,则下面提到的可选截止时间扩展方法将生成当月的最后一天,否则它将在datetime API中生成
public static DateTime AddMonthsE(this DateTime value,int numberOfMonths)
{
bool isEndDate = DateTime.DaysInMonth(value.Year, value.Month) == value.Day;
if(isEndDate)
{
var newDateTime = value.AddMonths(numberOfMonths);
return new DateTime(newDateTime.Year, newDateTime.Month, DateTime.DaysInMonth(newDateTime.Year, newDateTime.Month));
}
return value.AddMonths(numberOfMonths);
}
输入2010年2月28日凌晨12:00:00
输出加上1个月2010年3月31日凌晨12:00:00您也可以试试这个
int numberofmonths = Convert.ToInt32(textBox2.Text); //number of target months as integer
dateTimePicker1.Text = DateTime.Parse(strDate).Date.AddMonths(numberofmonths).ToString("d"); //new date displayed
如果你想在下个月的同一天保持一致,那么使用以下方法会不会更简单:
DateTime nextMonth=新的DateTime(thisMonth.Year,thisMonth.Month+1,thisMonth.Day);聪明-如果他保证已经有了月的最后一天,那就行了。如果他没有,结果与1月30日的AddMonths(1)相同,那不是。1月30日有什么解决方案吗?为什么不只是新的日期(date.Year,date.Month,1)AddMonths(1)AddDays(-1)in else?如果有任何答案满足您的需要,请点击旁边的“勾号”接受它。要微调算法:当日期是2月27日或2月1日时,您期望得到什么?是的,月份的最后一天也足够了,我想…我会在答案生效后立即标记:)如果您的意思是设置day属性-它是不可变的(这是C#-请参阅问题上的标记).Woah!抱歉。我不知道你不能在C#中这样做。如果你的约会是在12月呢?@Philippe Leybaert:谢谢你发现了这一点。检查我的编辑。效果很好!扩展方法的最后一行应该是return startOfNextMonth.AddMonths(months)-delta;
我认为,如果下个月的天数少于当前天数,则会出现问题
public static DateTime AddMonthsCustom(this DateTime source, int months)
{
var firstDayOfTargetMonth = new DateTime(source.Year, source.Month, 1).AddMonths(months);
var lastDayofSourceMonth = DateTime.DaysInMonth(source.Year, source.Month);
var lastDayofTargetMonth = DateTime.DaysInMonth(firstDayOfTargetMonth.Year, firstDayOfTargetMonth.Month);
var targetDay = source.Day > lastDayofTargetMonth ? lastDayofTargetMonth : source.Day;
if (source.Day == lastDayofSourceMonth)
targetDay = lastDayofTargetMonth;
return new DateTime(
firstDayOfTargetMonth.Year,
firstDayOfTargetMonth.Month,
targetDay,
source.Hour,
source.Minute,
source.Second,
source.Millisecond,
source.Kind);
}
[TestCase("2017-01-01T01:01:01.0010000Z", "2016-12-01T01:01:01.0010000Z", 1)]
[TestCase("2017-02-01T01:01:01.0010000Z", "2016-12-01T01:01:01.0010000Z", 2)]
[TestCase("2017-03-31T01:01:01.0010000Z", "2016-12-31T01:01:01.0010000Z", 3)]
[TestCase("2016-03-28T01:01:01.0010000Z", "2016-02-28T01:01:01.0010000Z", 1)]
[TestCase("2016-03-31T01:01:01.0010000Z", "2016-02-29T01:01:01.0010000Z", 1)]
[TestCase("2017-03-31T01:01:01.0010000Z", "2017-02-28T01:01:01.0010000Z", 1)]
[TestCase("2016-02-29T01:01:01.0010000Z", "2016-01-31T01:01:01.0010000Z", 1)]
[TestCase("2017-02-28T01:01:01.0010000Z", "2017-01-31T01:01:01.0010000Z", 1)]
[TestCase("2016-12-01T01:01:01.0010000Z", "2017-01-01T01:01:01.0010000Z", -1)]
[TestCase("2016-12-01T01:01:01.0010000Z", "2017-02-01T01:01:01.0010000Z", -2)]
[TestCase("2016-12-31T01:01:01.0010000Z", "2017-03-31T01:01:01.0010000Z", -3)]
[TestCase("2016-02-28T01:01:01.0010000Z", "2016-03-28T01:01:01.0010000Z", -1)]
public void DateTimeExtensions_AddMonthsCustom(DateTime expected, DateTime dateTime, int months)
{
// Arrange
expected = expected.ToUniversalTime();
dateTime = dateTime.ToUniversalTime();
// Act
DateTime result = dateTime.AddMonthsCustom(months);
// Assert
Assert.AreEqual(expected.Kind, result.Kind);
Assert.AreEqual(expected, result);
}
private DateTime AddMonthsRetainingEOM(DateTime someDate, int numMonths)
{
if (someDate.AddDays(1).Day == 1)
{
// someDate is EOM
someDate = someDate.AddMonths(numMonths);
// keep adding days if new someDate is not EOM
while (someDate.AddDays(1).Day != 1)
{
someDate = someDate.AddDays(1);
}
return someDate;
}
else
{
// not EOM - Just add months
return someDate.AddMonths(numMonths);
}
}
var t1 = new DateTime(2010,2,28);
var t2 = t1.AddDays((t1.Day * -1) + 1).AddMonths(2).AddMilliseconds(-1).Date;
// t2: {31.03.2010 00:00:00}
public static DateTime AddMonthsE(this DateTime value,int numberOfMonths)
{
bool isEndDate = DateTime.DaysInMonth(value.Year, value.Month) == value.Day;
if(isEndDate)
{
var newDateTime = value.AddMonths(numberOfMonths);
return new DateTime(newDateTime.Year, newDateTime.Month, DateTime.DaysInMonth(newDateTime.Year, newDateTime.Month));
}
return value.AddMonths(numberOfMonths);
}
int numberofmonths = Convert.ToInt32(textBox2.Text); //number of target months as integer
dateTimePicker1.Text = DateTime.Parse(strDate).Date.AddMonths(numberofmonths).ToString("d"); //new date displayed