Unity C#, How to addition X days to a date? - c#

In this part of code sDate show current date 2016/11/16, Now what is best way to add 7 days to current date? for example if current date is 2016/11/29 + 7 change to 2016/12/06. I'm looking for a way to addition an int value to a date.
string Year;
string Month;
string Day;
float time;
string sDate;
void Start ()
{
Year = System.DateTime.Now.Year.ToString();
Month = System.DateTime.Now.Month.ToString();
Day = System.DateTime.Now.Day.ToString();
int Y = int.Parse (Year);
int M = int.Parse (Month);
int D = int.Parse (Day);
if (Y >= 2016 & M >= 11 & D >= 21)
{
sDate = Year + "/" + Month + "/" + Day + " | Expired";
Debug.Log (sDate);
Application.Quit ();
}
else
{
sDate = Year + "/" + Month + "/" + Day + " | Working";
Debug.Log ("System date: " + sDate);
}
}

All you need to do is use the standard DateTime function AddDays:
DateTime result = original.AddDays(n);
where original is the original date and n is the number of days you want to add.
I'd also check the rest of the documentation on the DateTime structure as there are a lot simpler ways of doing what you are trying here. As mentioned in the comments you can construct a DateTime object from it's components:
DateTime referenceDate = new DateTime(2016, 11, 15);
and then do comparisons on that:
if (testDate >= referenceDate)
{
// Do something
}
etc.

Related

Simplest way to calculate anniversary given a date in the past?

i need a function that calculates if there is an upcoming anniversary for a person given a start date in the past and today's current date. I found this code below but looking at the below code and I have the feeling that there is a much simpler way to calculate this without required this for loop:
private const int ANNIVERSARY_ALERT = 10;
public virtual string UpcomingMilestone
{
get
{
var years = Years() + 2;
for (int year = 0; year < years; year++)
{
int days = year * 365;
int dayDiff = days - NumberOfDays;
if (dayDiff == 0)
{
return year + " year milestone";
}
if (dayDiff < ANNIVERSARY_ALERT && dayDiff > 0)
{
return year + " year milestone in " + dayDiff + " days";
}
}
return string.Empty;
}
}
public virtual int NumberOfDays
{
get
{
TimeSpan ts = DateTime.Today - StartDate.Value;
return (int)ts.TotalDays;
}
}
public virtual int Years()
{
TimeSpan span = DateTime.Now.Subtract(StartDate.Value);
return (int)(span.Days / 365.25); // leap years included
}
Can anyone suggest a way to calculate this above without having to do this loop? This is more for code maintainability versus any performance considerations.
Use the relevant parts of the startdate to compose a new DateTime:
//My birthday, feel free to put this date in your calendars!
var startDate = new DateTime(1976, 2, 29);
//Get the anniversary date for this year
DateTime nextAnniversary;
try
{
nextAnniversary = new DateTime(DateTime.Today.Year, startDate.Month, startDate.Day);
}
catch(ArgumentOutOfRangeException)
{
//DateTime conversion failed, try next day in the year
nextAnniversary = new DateTime(DateTime.Today.Year, startDate.AddDays(1).Month, startDate.AddDays(1).Day);
}
//Check if this year's anniversary has already happened
if(nextAnniversary < DateTime.Today) nextAnniversary = nextAnniversary.AddYears(1);
This should do it. You need to provide TimeSpan range that can be a day or a week, and date which you are matching anniversary to.
public bool Upcomming(DateTime date, TimeSpan range){
var newdate = new Date(DateTime.Now.Year, date.Month, date.Day);
return newdate - DateTime.Now < range;
}
int anniversaryYear = DateTime.Now.Year - StartDate.Year + 1;
DateTime nextAnniversary = StartDate.AddYears(anniversaryYear);
if (nextAnniversary == DateTime.Now)
{
return anniverasryYear + " year milestone";
}
if (DateTime.Now > nextAnniverasry)
{
anniverasryYear++;
nextAnniversary = StartDate.AddYears(anniversaryYear);
}
var daysTillNext = Math.Abs( (nextAnniversary - DateTime.Now).TotalDays );
return string.Format("{0} milestone in {1}", anniversaryYear, daysTillNext);
These methods should be sufficient for your purposes.
public DateTime GetNextAnniversaryDate(DateTime anniversary)
{
var today = DateTime.Today;
var year = anniversary.Month < today.Month ||
(anniversary.Month == today.Month && anniversary.Day < today.Day)
? today.Year + 1 : today.Year;
return anniversary.Month == 2 && anniversary.Day == 29 &&
!DateTime.IsLeapYear(year)
? new DateTime(year, 2, 28)
: new DateTime(year, anniversary.Month, anniversary.Day);
}
public int GetDaysUntilNextAnniversary(DateTime anniversary)
{
var nextDate = GetNextAnniversaryDate(anniversary);
return (int)(nextDate - DateTime.Today).TotalDays;
}
Note that we are specifically electing to celebrate leap-day anniversaries on Feb 28th when the anniversary year is not a leap year. You could change that to March 1 if desired.
Also note that this question assumes that the day of the person in question is the same day as the computer's local clock. This might not be true, for example if the local machine is in a time zone that is ahead of the user's time zone, then it might be one day off. If you want to take that into consideration, then you could use TimeZoneInfo and DateTime.UtcNow. Or you could use Noda Time. More about this on my blog.

How to substract two dates resulting in days or weeks?

I'm looking for a function in which I can enter 2 dates:
Starting like this:
public static String getDaysOrWeeksFromDateDiff(DateTime first, DateTime second)
{
//this function will substract the date from the other and result days if < 8 and weeks if > 7
return "1 week";
}
I've tried this function below, but it gives me a negative date (I've missed the year somehow in the calculation)
public static String getDaysOrWeeksFromDateDiff(DateTime first, DateTime second)
{
var cal = new GregorianCalendar(GregorianCalendarTypes.Localized);
var weeknr = cal.GetWeekOfYear(first, CalendarWeekRule.FirstDay, DayOfWeek.Monday);
var weeknr2 = cal.GetWeekOfYear(second, CalendarWeekRule.FirstDay, DayOfWeek.Monday);
String strReturnValue;
if (weeknr == weeknr2)
{
var dagen = first.Day - second.Day;
strReturnValue = (dagen == 0 ? "today" : (dagen == 1 ? "1 day" : dagen + " days"));
}
else
{
strReturnValue = (weeknr - weeknr2 == 1 ? "1 week" : weeknr - weeknr2 + " weeks");
}
return strReturnValue;
}
You can subtract dates directly:
TimeSpan difference = second - first;
This returns a TimeSpan object, which you can query easily, e.g.
if (difference.Days >= 8) ...
Converting the number of Days into weeks should be a trivial exercise since every week has exactly 7 days...
(Note that Days will give you the number of days as an integer, whereas TotalDays will include fractional days.)
You can use Time span class
public static String getWeekOrMonthFromDateDiff(DateTime first, DateTime second)
{
var span = second - first;
if (span.Days <= 7)
return span.Days + " day(s)";
else
return span.Days / 7 + " week(s)";
}
You can simply do
TimeSpan diff = first - second;
Then you can do
int weekCount = diff.TotalDays / 7;
I've done something like this some days ago:
private string GetTimeSpan(DateTime toDateTime, DateTime fromDateTime)
{
TimeSpan ts = toDateTime- fromDateTime;
if (ts.Days < 0)
{
return "since " + ts.Days.ToString().Replace("-", string.Empty) + " Days";
}
else if (ts.Hours < 1)
{
return "in " + ts.Minutes + " Minutes";
}
else if (ts.Days < 1)
{
return "in " + ts.Hours + " Hours";
}
else if (ts.Days < 7)
{
return "in " + ts.Days + " Days";
}
else
{
return "in " + ts.Days / 7 + " Weeks";
}
}
Modify it the way you Need it :)
For a length of time like this, you should use TimeSpan instead of DateTime, and then calculate the number of weeks from the property TotalDays.
void func(DateTime t1, DateTime t2)
{
days = (t2 - t1).TotalDays;
weeks = days/7;
year = weeks/52;
}

How to convert the timestamp from 24 hr format to 12 hr format in C#?

I want to convert to timestamp in 24hrs fromat to 12 hrs format.Here is my code with output mentioned in braces.
date = Dyear + "" + Dmonth + "" + Dday + " " + strhour+""+strminute+""+"00"; (20130628 142900)
DateTime dt = new DateTime(Convert.ToInt32(Dyear), Convert.ToInt32(Dmonth), Convert.ToInt32(Dday), Convert.ToInt32(strhour), Convert.ToInt32(strminute), 00);(6/28/2013 2:29:00 PM)
TimeSpan ts = dt.Subtract(new DateTime(1970, 01, 01, 00, 00, 00));(15884.14:29:00)
String sTimeStamp = ts.TotalMilliseconds.ToString("0"); (1372429740000)
the above sTimeStamp will be in MM/DD/YYYY HH:MM:ttt format(06/28/2013 19:59:000) like "1372429740".
I want to display the time stamp in 12 hr format like MM/DD/YYYY hh:mm:ttt format(06/28/2013 07:59:000) like "1372386540"
Bear in mind that the format you refer is just for displaying purposes. If you want to account for this modification in your calculations (putting 2 instead of 14), a 12h lag would appear.
If you just want to display 6/28/2013 2:29:00, you can use the following string (the calculated miliseconds will not be affected):
string sTimeStamp = dt.ToString("MM/dd/yyyy hh:mm:ss tt");
If what you want is performing this change during the time calculations (not sure about the reason for doing that), you have to modify the way in which dt is generated (this time, the calculated milisenconds will be affected: 12h lag with respect to the option above):
DateTime dt = new DateTime(Convert.ToInt32(Dyear), Convert.ToInt32(Dmonth), Convert.ToInt32(Dday), Convert.ToInt32(new DateTime(2000, 1, 1, Convert.ToInt32(strhour), 0, 0).ToString("hh:mm tt").Split(':')[0]), Convert.ToInt32(strminute), 0);
In this second case, dt will always be formed on account of the "12h understanding" of the input value; for example: it will account for 2(am) if strhour is either 2 or 14.
internal static string ConvertTo_12_Format(string str)
{
//using system function
DateTime dt = DateTime.ParseExact(str, "HH:mm", System.Globalization.CultureInfo.InvariantCulture);
string s = dt.ToString("hh:mm");
//using logic
StringBuilder sb = new StringBuilder();
int h1 = (int)str[0] - '0';
int h2 = (int)str[1] - '0';
string Meridien;
int hh = h1 * 10 + h2;
if (hh < 12)
{
Meridien = "AM";
}
else
Meridien = "PM";
hh %= 12;
int c1 = (int)str[3] - '0';
int c2 = (int)str[4] - '0';
if (hh == 0)
{
sb.Append("12:");
//18:30
// Printing minutes and seconds
sb.Append(c1.ToString() + c2.ToString());
}
else
{
if(hh < 10)
{
sb.Append("0" + hh + ":");
sb.Append(c1.ToString() + c2.ToString());
}else
{
sb.Append(hh + ":");
sb.Append(c1.ToString() + c2.ToString());
}
}
sb.Append(" "+Meridien);
return sb.ToString();
}

How do I represent date range for months that donot have 31 days in c#?

I want to find the leaves taken by an employee in a month.
The code works perfectly for all the dates.
Now, if I want to find the leaves taken by the employee in January, the range is:
DateTime first = Convert.ToDateTime(DateTime.Now.Month + "01" + DateTime.Now.Year);
DateTime end = Convert.ToDateTime(DateTime.Now.Month + "31" + DateTime.Now.Year);
The problem is that some months do not have 31 days. Is there an easy way with which I could assign the variables From and To the range. An error would be given when the months's Feburary or April because they donot have 31 days.
The code for executing the search is :
returnedRows = LeaveDS.Tables["Leave"].Select("LeaveDate >= #" + first + "# AND LeaveDate <= #" + end + "#");
You could do something like this:
DateTime end = first.AddMonths(1).AddDays(-1);
DateTime.DaysInMonth(DateTime.Now.Year, DateTime.Now.Month)
it'll give you the days in a month.
Use DateTime.DaysInMonth(int year, int month)
int days = DateTime.DaysInMonth(2012, 2);
int days2 = DateTime.DaysInMonth(2011, 2);
output:
days = 29
days2 = 28
You can get the number of days in a month by DateTime.DaysInMonth(year,month), and use this as basis for your query.
The alternative is to use the first of each month but alter your select query to be less than the end date.
DateTime first = Convert.ToDateTime(DateTime.Now.Month + "01" + DateTime.Now.Year);
DateTime end = first.AddMonths(1); // Becomes 01 of next month
returnedRows = LeaveDS.Tables["Leave"].Select("LeaveDate >= #" + first + "# AND LeaveDate < #" + end + "#");
There is a great method to get the days in a month, it's called DateTime.DaysInMonth
DateTime end = new DateTime(first.Year, first.Month, DateTime.DaysInMonth(first.Year, first.Month);
var enddate = DateTime.Now.AddMonths(1);
DateTime end = new DateTime(enddate.Year,enddate.Month,1);
By the way, if you're using .NET 3.5 or greater Linq-To-DataSet will simplify and improve the code:
int month = 2; // f.e. for february
var currentCalendar = System.Globalization.CultureInfo.CurrentCulture.Calendar;
int daysInMonth = currentCalendar.GetDaysInMonth(month);
DateTime start = new DateTime(DateTime.Now.Year, month, 1);
DateTime end = new DateTime(DateTime.Now.Year, month, daysInMonth);
var filteredRows = LeaveDS.Tables["Leave"].AsEnumerable()
.Where(r => r.Field<DateTime>("LeaveDate").Date >= start
&& r.Field<DateTime>("LeaveDate").Date <= end );
// use ToArray for an array, CopyToDataTable for a DataTable etc.

How to calculate actual months difference (calendar year not approximation) between two given dates in C#?

Example: given two dates below, finish is always greater than or equal to start
start = 2001 Jan 01
finish = 2002 Mar 15
So from 2001 Jan 01 to the end of 2002 Feb
months = 12 + 2 = 14
For 2002 March
15/30 = 0.5
so grand total is 14.5 months difference.
It's very easy to work out by hand but how do I code it elegantly? At the moment I have the combination of a lot of if else and while loops to achieve what I want but I believe there are simpler solutions out there.
Update: the output needs to be precise (not approximation) for example:
if start 2001 Jan 01 and finish 2001 Apr 16, the output should be 1 + 1 + 1= 3 (for Jan, Feb and Mar) and 16 / 31 = 0.516 month, so the total is 3.516.
Another example would be if I start on 2001 Jul 5 and finish on 2002 Jul 10, the output should be 11 month up to the end of June 2002, and (31-5)/31 = 0.839 and 10/31 = 0.323 months, so the total is 11 + 0.839 + 0.323 = 12.162.
I extended Josh Stodola's code and Hightechrider's code:
public static decimal GetMonthsInRange(this IDateRange thisDateRange)
{
var start = thisDateRange.Start;
var finish = thisDateRange.Finish;
var monthsApart = Math.Abs(12*(start.Year - finish.Year) + start.Month - finish.Month) - 1;
decimal daysInStartMonth = DateTime.DaysInMonth(start.Year, start.Month);
decimal daysInFinishMonth = DateTime.DaysInMonth(finish.Year, finish.Month);
var daysApartInStartMonth = (daysInStartMonth - start.Day + 1)/daysInStartMonth;
var daysApartInFinishMonth = finish.Day/daysInFinishMonth;
return monthsApart + daysApartInStartMonth + daysApartInFinishMonth;
}
I gave an int answer before, and then realized what you asked for a more precise answer. I was tired, so I deleted and went to bed. So much for that, I was unable to fall asleep! For some reason, this question really bugged me, and I had to solve it. So here you go...
static void Main(string[] args)
{
decimal diff;
diff = monthDifference(new DateTime(2001, 1, 1), new DateTime(2002, 3, 15));
Console.WriteLine(diff.ToString("n2")); //14.45
diff = monthDifference(new DateTime(2001, 1, 1), new DateTime(2001, 4, 16));
Console.WriteLine(diff.ToString("n2")); //3.50
diff = monthDifference(new DateTime(2001, 7, 5), new DateTime(2002, 7, 10));
Console.WriteLine(diff.ToString("n2")); //12.16
Console.Read();
}
static decimal monthDifference(DateTime d1, DateTime d2)
{
if (d1 > d2)
{
DateTime hold = d1;
d1 = d2;
d2 = hold;
}
int monthsApart = Math.Abs(12 * (d1.Year-d2.Year) + d1.Month - d2.Month) - 1;
decimal daysInMonth1 = DateTime.DaysInMonth(d1.Year, d1.Month);
decimal daysInMonth2 = DateTime.DaysInMonth(d2.Year, d2.Month);
decimal dayPercentage = ((daysInMonth1 - d1.Day) / daysInMonth1)
+ (d2.Day / daysInMonth2);
return monthsApart + dayPercentage;
}
Now I shall have sweet dreams. Goodnight :)
What you want is probably something close to this ... which pretty much follows your explanation as to how to calculate it:
var startofd1 = d1.AddDays(-d1.Day + 1);
var startOfNextMonthAfterd1 = startofd1.AddMonths(1); // back to start of month and then to next month
int daysInFirstMonth = (startOfNextMonthAfterd1 - startofd1).Days;
double fraction1 = (double)(daysInFirstMonth - (d1.Day - 1)) / daysInFirstMonth; // fractional part of first month remaining
var startofd2 = d2.AddDays(-d2.Day + 1);
var startOfNextMonthAfterd2 = startofd2.AddMonths(1); // back to start of month and then to next month
int daysInFinalMonth = (startOfNextMonthAfterd2 - startofd2).Days;
double fraction2 = (double)(d2.Day - 1) / daysInFinalMonth; // fractional part of last month
// now find whole months in between
int monthsInBetween = (startofd2.Year - startOfNextMonthAfterd1.Year) * 12 + (startofd2.Month - startOfNextMonthAfterd1.Month);
return monthsInBetween + fraction1 + fraction2;
NB This has not been tested very well but it shows how to handle problems like this by finding well known dates at the start of months around the problem values and then working off them.
While loops for date time calculations are always a bad idea: see http://www.zuneboards.com/forums/zune-news/38143-cause-zune-30-leapyear-problem-isolated.html
Depending on how exactly you want your logic to work, this would at least give you a decent approximation:
// 365 days per year + 1 day per leap year = 1461 days every 4 years
// But years divisible by 100 are not leap years
// So 1461 days every 4 years - 1 day per 100th year = 36524 days every 100 years
// 12 months per year = 1200 months every 100 years
const double DaysPerMonth = 36524.0 / 1200.0;
double GetMonthsDifference(DateTime start, DateTime finish)
{
double days = (finish - start).TotalDays;
return days / DaysPerMonth;
}
One way to do this is that you'll see around quite a bit is:
private static int monthDifference(DateTime startDate, DateTime endDate)
{
int monthsApart = 12 * (startDate.Year - endDate.Year) + startDate.Month - endDate.Month;
return Math.Abs(monthsApart);
}
However, you want "partial months" which this doesn't give. But what is the point in comparing apples (January/March/May/July/August/October/December) with oranges (April/June/September/November) or even bananas that are sometimes coconuts (February)?
An alternative is to import Microsoft.VisualBasic and do this:
DateTime FromDate;
DateTime ToDate;
FromDate = DateTime.Parse("2001 Jan 01");
ToDate = DateTime.Parse("2002 Mar 15");
string s = DateAndTime.DateDiff (DateInterval.Month, FromDate,ToDate, FirstDayOfWeek.System, FirstWeekOfYear.System ).ToString();
However again:
The return value for
DateInterval.Month is calculated
purely from the year and month parts
of the arguments
[Source]
Just improved Josh's answer
static decimal monthDifference(DateTime d1, DateTime d2)
{
if (d1 > d2)
{
DateTime hold = d1;
d1 = d2;
d2 = hold;
}
decimal monthsApart = Math.Abs((12 * (d1.Year - d2.Year)) + d2.Month - d1.Month - 1);
decimal daysinStartingMonth = DateTime.DaysInMonth(d1.Year, d1.Month);
monthsApart = monthsApart + (1-((d1.Day - 1) / daysinStartingMonth));
// Replace (d1.Day - 1) with d1.Day incase you DONT want to have both inclusive difference.
decimal daysinEndingMonth = DateTime.DaysInMonth(d2.Year, d2.Month);
monthsApart = monthsApart + (d2.Day / daysinEndingMonth);
return monthsApart;
}
The answer works perfectly and while the terseness of the code makes it very small I had to break everything apart into smaller functions with named variables so that I could really understand what was going on... So, basically I just took Josh Stodola's code and Hightechrider's mentioned in Jeff's comment and made it smaller with comments explaining what was going on and why the calculations were being made, and hopefully this may help someone else:
[Test]
public void Calculate_Total_Months_Difference_Between_Two_Dates()
{
var startDate = DateTime.Parse( "10/8/1996" );
var finishDate = DateTime.Parse( "9/8/2012" ); // this should be now:
int numberOfMonthsBetweenStartAndFinishYears = getNumberOfMonthsBetweenStartAndFinishYears( startDate, finishDate );
int absMonthsApartMinusOne = getAbsMonthsApartMinusOne( startDate, finishDate, numberOfMonthsBetweenStartAndFinishYears );
decimal daysLeftToCompleteStartMonthPercentage = getDaysLeftToCompleteInStartMonthPercentage( startDate );
decimal daysCompletedSoFarInFinishMonthPercentage = getDaysCompletedSoFarInFinishMonthPercentage( finishDate );
// .77 + .26 = 1.04
decimal totalDaysDifferenceInStartAndFinishMonthsPercentage = daysLeftToCompleteStartMonthPercentage + daysCompletedSoFarInFinishMonthPercentage;
// 13 + 1.04 = 14.04 months difference.
decimal totalMonthsDifference = absMonthsApartMinusOne + totalDaysDifferenceInStartAndFinishMonthsPercentage;
//return totalMonths;
}
private static int getNumberOfMonthsBetweenStartAndFinishYears( DateTime startDate, DateTime finishDate )
{
int yearsApart = startDate.Year - finishDate.Year;
const int INT_TotalMonthsInAYear = 12;
// 12 * -1 = -12
int numberOfMonthsBetweenYears = INT_TotalMonthsInAYear * yearsApart;
return numberOfMonthsBetweenYears;
}
private static int getAbsMonthsApartMinusOne( DateTime startDate, DateTime finishDate, int numberOfMonthsBetweenStartAndFinishYears )
{
// This may be negative i.e. 7 - 9 = -2
int numberOfMonthsBetweenStartAndFinishMonths = startDate.Month - finishDate.Month;
// Absolute Value Of Total Months In Years Plus The Simple Months Difference Which May Be Negative So We Use Abs Function
int absDiffInMonths = Math.Abs( numberOfMonthsBetweenStartAndFinishYears + numberOfMonthsBetweenStartAndFinishMonths );
// Subtract one here because we are going to use a perecentage difference based on the number of days left in the start month
// and adding together the number of days that we've made it so far in the finish month.
int absMonthsApartMinusOne = absDiffInMonths - 1;
return absMonthsApartMinusOne;
}
/// <summary>
/// For example for 7/8/2012 there are 24 days left in the month so about .77 percentage of month is left.
/// </summary>
private static decimal getDaysLeftToCompleteInStartMonthPercentage( DateTime startDate )
{
// startDate = "7/8/2012"
// 31
decimal daysInStartMonth = DateTime.DaysInMonth( startDate.Year, startDate.Month );
// 31 - 8 = 23
decimal totalDaysInStartMonthMinusStartDay = daysInStartMonth - startDate.Day;
// add one to mark the day as being completed. 23 + 1 = 24
decimal daysLeftInStartMonth = totalDaysInStartMonthMinusStartDay + 1;
// 24 / 31 = .77 days left to go in the month
decimal daysLeftToCompleteInStartMonthPercentage = daysLeftInStartMonth / daysInStartMonth;
return daysLeftToCompleteInStartMonthPercentage;
}
/// <summary>
/// For example if the finish date were 9/8/2012 we've completed 8 days so far or .24 percent of the month
/// </summary>
private static decimal getDaysCompletedSoFarInFinishMonthPercentage( DateTime finishDate )
{
// for septebmer = 30 days in month.
decimal daysInFinishMonth = DateTime.DaysInMonth( finishDate.Year, finishDate.Month );
// 8 days divided by 30 = .26 days completed so far in finish month.
decimal daysCompletedSoFarInFinishMonthPercentage = finishDate.Day / daysInFinishMonth;
return daysCompletedSoFarInFinishMonthPercentage;
}
This solution calculates whole months and then adds the partial month based on the end of the time period. This way it always calculates full months between the dates' day-of-month and then calculates the partial month based on the number of remaining days.
public decimal getMonthDiff(DateTime date1, DateTime date2) {
// Make parameters agnostic
var earlyDate = (date1 < date2 ? date1 : date2);
var laterDate = (date1 > date2 ? date1 : date2);
// Calculate the change in full months
decimal months = ((laterDate.Year - earlyDate.Year) * 12) + (laterDate.Month - earlyDate.Month) - 1;
// Add partial months based on the later date
if (earlyDate.Day <= laterDate.Day) {
decimal laterMonthDays = DateTime.DaysInMonth(laterDate.Year, laterDate.Month);
decimal laterPartialMonth = ((laterDate.Day - earlyDate.Day) / laterMonthDays);
months += laterPartialMonth + 1;
} else {
var laterLastMonth = laterDate.AddMonths(-1);
decimal laterLastMonthDays = DateTime.DaysInMonth(laterLastMonth.Year, laterLastMonth.Month);
decimal laterPartialMonth = ((laterLastMonthDays - earlyDate.Day + laterDate.Day) / laterLastMonthDays);
months += laterPartialMonth;
}
return months;
}
The calculation below is one that is according the way the Dutch Tax Authority wants months calculated. This means that when the starts day is for example feb 22, march 23 should be result in something above 1 and not just something like 0.98.
private decimal GetMonthDiffBetter(DateTime date1, DateTime date2)
{
DateTime start = date1 < date2 ? date1 : date2;
DateTime end = date1 < date2 ? date2 : date1;
int totalYearMonths = (end.Year - start.Year) * 12;
int restMonths = end.Month - start.Month;
int totalMonths = totalYearMonths + restMonths;
decimal monthPart = (decimal)end.Day / (decimal)start.Day;
return totalMonths - 1 + monthPart;
}`
This should get you where you need to go:
DateTime start = new DateTime(2001, 1, 1);
DateTime finish = new DateTime(2002, 3, 15);
double diff = (finish - start).TotalDays / 30;
the framework as a TimeSpan object that is a result of subtracting two dates.
the subtraction is already considering the various option of February(28/29 days a month) so in my opinion this is the best practice
after you got it you can format it the way you like best
DateTime dates1 = new DateTime(2010, 1, 1);
DateTime dates2 = new DateTime(2010, 3, 15);
var span = dates1.Subtract(dates2);
span.ToString("your format here");
private Double GetTotalMonths(DateTime future, DateTime past)
{
Double totalMonths = 0.0;
while ((future - past).TotalDays > 28 )
{
past = past.AddMonths(1);
totalMonths += 1;
}
var daysInCurrent = DateTime.DaysInMonth(future.Year, future.Month);
var remaining = future.Day - past.Day;
totalMonths += ((Double)remaining / (Double)daysInCurrent);
return totalMonths;
}

Categories