C# DateTime AddDays off by one - c#

Can anyone explain to me why this unit test is failing?
I scoured through MSDN expecting to find an explanation, for example I was expecting to find something like, "the starting day is not inclusive" etc. but I found no such statement. Therefore I am confused as to why this seems to be off by one day.
The following will result in Sept 29th. I am expecting Sept 30th.
[Test]
public void AddDaysBug_OffByOne()
{
DateTime end = new DateTime(2018,10,3);
DateTime fourDaysEarlier = end.AddDays(-4);
// this fails. 29!=30
Assert.AreEqual(fourDaysEarlier.Day,30, "four days prior to October 3 is Sept 30");
}

Lets take these days one at a time for illustration...
3rd - 1 = 2nd
2nd - 1 = 1st
1st - 1 = 30th
30th - 1 = 29th
There is no zero day in months as with "normal" numbers.

Setp: 28, 29, 30
Oct: 1, 2, 3
So: (3 Oct - 4 day) is equal to 29

Sept 29th seems to be correct answer.
It's easy to see if you subtracting one day at a time.
-1 day, 10/02/2018
-2 day, 10/01/2018
-3 day, 09/30/2018
-4 day, 09/29/2018

Related

How to get 29 Feb using AddYears method in c#

We use a job which runs every day and perform some action for a day one year ahead.
Actually we just use something like: DateTime.UtcNow.AddYears(1).
But it seems not possible to get a 29 February(e.g for 2020) using this technique:
var target = new DateTime(2020, 2, 29);
bool result = (target == target.AddYears(-1).AddYears(1));//false
So is it possible to target a 29 February in future somehow?
No. The Documentation states:
If value + DateTime.Year is also a leap year, the return value represents the leap day in that year. For example, if four years is added to February 29, 2012, the date returned is February 29, 2016.
If value + DateTime.Year is not a leap year, the return value represents the day before the leap day in that year. For example, if one year is added to February 29, 2012, the date returned is February 28, 2013.
This means if you add a year you will always get Feb 28th. The only way to get 29th via AddYears is if you add a multiple of 4.
No, this is by design.
If the current instance represents the leap day in a leap year, the
return value depends on the target date:
If value + DateTime.Year is also a leap year, the return value
represents the leap day in that year. For example, if four years is
added to February 29, 2012, the date returned is February 29, 2016.
If value + DateTime.Year is not a leap year, the return value
represents the day before the leap day in that year. For example, if
one year is added to February 29, 2012, the date returned is February
28, 2013.
1 year after 29th Feb 2020 should be 28th Feb 2021 since it is not a leap year. But in such a case, all the years after 2021 will work as a 28th February.
Other than this, ask yourself, what is the meaning of a "year" for you? How many days in a month? How many days in a year? Is it 365? 366? Or as wikipedia stated 365.2425? Also, which calendar we are talking about?
Frameworks, libraries etc.. does not work like people think. They work based on a set of rules that defined before. .NET Framework defined this rule as such. So, when you add a year to a DateTime instance, what they decide is month part has to stay same, year part will change for how many years will be added, and the day part must be a valid one.
You could cheat the system a bit by taking "the day before march 1st" instead.
stub:
DateTime today = DateTime.UtcNow
if (today.month == 2)
{
if(today.day == 28 || today.day == 29)
{
today.AddDays(1).AddYears(1).AddDays(-1)
}
}
this converts your feb 28 on non-leapyears in march 1st, adds a year, and goes to the day before that.
If the next year also is not a leapyear, you will still get feb 28, but if next year is a leapyear, the result will be feb 29.
this does not deal yet with the situation that this year is a leapyear, as this code will then return febuary 27th instead though
Function that return the next 29. feb. Maybe it helps.
using System;
public class Program
{
public static DateTime NextTwentyNineFeb()
{
int year = DateTime.Now.Year;
while(true){
try{
var target = new DateTime(year, 2, 29);
Console.WriteLine(target);
return target;
}
catch
{
year++;
}
}
}
}
As NibblyPig stated, this isn't possible. However, if you are actually just looking for the end of the month, then you can use new DateTime(year, month + 1, 0).AddDays(-1)

Get week number for the given date c#

I have tried searching for a solution which gives the correct week number for the date value.
link1, link2,link3
Followed the methods in the above links, but for the date 30/12/2014, I get the week number as 53. but it falls as 1st week of 2015 year.
I tried the below methods to get the week number of the year for the specific date.
private int GetWeekNumberOfTheYear() {
var currentCulture = CultureInfo.CurrentCulture;
// option 1
var weekNo = currentCulture.Calendar.GetWeekOfYear(DateTime.Now,currentCulture.DateTimeFormat.CalendarWeekRule, currentCulture.DateTimeFormat.FirstDayOfWeek);
// option 2
var weekNo = CultureInfo.InvariantCulture.Calendar.GetWeekOfYear(DateTime.Now, CalendarWeekRule.FirstDay, DayOfWeek.Monday);
return weekNo; }
Is the method above is correct to return 53 as week number or it should be 1 ?
Is there any mistake in the above code. Suggestions please.
EDIT :
Found many searches specified, Dec 29th 2014 to 4th Jan 2015 as 1st week of year 2015.
So my confusion is the present week must be taken as 53rd Week or 1st Week.
http://week-number.net/calendar-with-week-numbers-2014.html
http://www.epochconverter.com/date-and-time/weeknumbers-by-year.php
If you're looking for the ISO-8601 week-of-week-year, you could use my Noda Time project:
var date = new LocalDate(2014, 12, 30);
var week = date.WeekOfWeekYear; // 1
var weekYear = date.WeekYear; // 2015
You can get a LocalDate from a DateTime via a LocalDateTime, but ideally you'd use the Noda Time times as widely as possible through your project. (That's the way I'd hope you'd get the maximum benefit, anyway.)

Cron Expression to execute cron triggers on every week at 3 pm and start date from 25th April 2012

I am in need to create a cron triggers expression which should fire on every week at 3 pm and start date from 25th April 2012.
Please note i am using CronTriggerImpl and i want to use it in the C# DotNet.
Thanks in advance
The expressions have the format
sec min hour DayOfMonth Month DayOfWeek Year
so with 3 expressions you should be able to get what you want.
0 0 3 25-30 4 0 2012
0 0 3 * 5-12 0 2012
0 0 3 * * 0 2013-2099
Line 1 says: 3 pm on first day of week on day of month larger-or-equal to 25th in april month in year 2012
Line 2 says: 3 pm on first day of week on any day of month in months largeror-equal to may in year 2012
Line 3 says: 3 pm on first day of week on any day of month in any month in year larger-or-equal to 2013.
Otherwise just use the simple expression
0 0 3 * * 0 *
combined with
newTrigger().startAt(new DateTime("2012-04-25"))
Disclaimer: I've not actually tried this. :)
Edit: I'm not sure quartz likes open ranges... so they're closed now.

GetMonthName: Valid values are between 1 and 13, inclusive. Why?

I accidentally passed 0 into DateTimeFormatInfo's GetMonthName method:
DateTimeFormatInfo info = new DateTimeFormatInfo();
var monthName = info.GetMonthName(0);
and got a System.ArgumentOutOfRangeException with this error message: Valid values are between 1 and 13, inclusive.
Passing in 1 through to 12 return "January" through to "December" but passing in 13 returns an empty string.
I can see why month numbers are not zero indexed, but what's month 13 for?
It's because calendar objects can accomodate 13 months (to handle calendars based on lunar months), see MSDN:
http://msdn.microsoft.com/en-us/library/system.globalization.datetimeformatinfo.getmonthname.aspx
Calendar objects can accommodate calendars with 13 months. For 12-month calendars, the empty string is always returned as the name of the 13th month.
According to MSDN
Calendar objects can accommodate
calendars with 13 months. For 12-month
calendars, the empty string is always
returned as the name of the 13th
month.
I guess it is used to determine the leap day in the julian calendar ( http://en.wikipedia.org/wiki/Julian_calendar ). As most of use use Gregorian calender just do not worry.

How to get list of monthly periods?

I have starting date and number of months. I need to create specific number of monthly periods for example:
var startingDate = new DateTime(2010,1,15);
var months = 3;
for (int i = 0; i < months; i++)
{
Console.WriteLine("{0} from {1} to {2}", i + 1, startingDate.AddMonths(i),
startingDate.AddMonths(i + 1).AddDays(-1));
}
OUTPUT:
1 from 2010-1-15 to 2010-2-14
2 from 2010-2-15 to 2010-3-14
3 from 2010-3-15 to 2010-4-14
In this case code is simple and it works.
However when startDate is DateTime(2010,1,31) result is:
OUTPUT:
1 from 2010-1-31 to 2010-2-27
2 from 2010-2-28 to 2010-3-30
3 from 2010-3-31 to 2010-4-29
Are these periods correct?
The periods do look funky but they are correct.
If your periods are starting on the last day of the month they will end on the second to last day of the next month.
You get to choose if they are right or wrong. Here is what I mean :
If you start your period on the 15th of January, are you starting 14 days after the first day of the month, or are you starting 16 days before the last?
It can get even more tricky. If the 15th is a Tuesday, is your period defined as starting the 3rd Tuesday of a given month?
There is a lot of literature about this in the financial community, since the Day Count Conventions, the Business Days, Rolling Conventions, etc. can make a lot of difference in the pricing of a financial product, and in the cash flows associated with it.

Categories

Resources