Related
In a scenario where you would need to calculate the next 'Billing date' if the DAY (2nd, 25th, etc) is known, how can you calculate the number of days left until the next bill payment?
Explanation:
Tom's bill gets generated on the 4th of every month
What's the best way/logic to calculate the days left until the next bill? For example, if today is the 28th of this month, the result would be 6 days left
What we know:
Bill Generation Date is known
Today's Date is known
What I've done so far:
int billingDay = 4; //The day the bill gets generated every month
DateTime today = DateTime.Today; //Today's date
How would I continue this to calculate the next billing date?
P.S: Sorry if this sounds lame, I just couldn't wrap my head around it :)
I think this works:
private int GetNumDaysToNextBillingDate(int billingDayOfMonth)
{
DateTime today = DateTime.Today;
if (today.Day <= billingDayOfMonth)
{
return (new DateTime(today.Year, today.Month, billingDayOfMonth) - today).Days;
}
else
{
var oneMonthFromToday = today.AddMonths(1);
var billingDateNextMonth =
new DateTime(oneMonthFromToday.Year,
oneMonthFromToday.Month, billingDayOfMonth);
return (billingDateNextMonth - today).Days;
}
}
How about:
int billingDay = 4;
DateTime today = DateTime.UtcNow;
DateTime billing = today.Day >= billingDay
? new DateTime(today.AddMonths(1).Year, today.AddMonths(1).Month, billingDay)
: new DateTime(today.Year, today.Month, billingDay);
TimeSpan left = billing - today;
This uses a loop but is less prone to error as it takes into account month and year changes:
int DaysUntilBilling(int billingDay, DateTime referenceDate)
{
int count = 0;
while (referenceDate.AddDays(count).Day != billingDay)
{
count++;
};
return count;
}
You of course don't need to pass a DateTime in as an argument if you are always using today's date, but this helps to test that that for different inputs, you get the desired output:
int billingDay = 4;
DaysUntilBilling(billingDay, DateTime.Now); //26 (today is 9th Aug 2016)
DaysUntilBilling(billingDay, new DateTime(2016, 09, 03); //1
DaysUntilBilling(billingDay, new DateTime(2016, 09, 04); //0
DaysUntilBilling(billingDay, new DateTime(2016, 08, 05); //30
DaysUntilBilling(billingDay, new DateTime(2016, 12, 19); //16
This link might help you :
https://msdn.microsoft.com/en-us/library/system.datetime.daysinmonth(v=vs.110).aspx
What you can do is something like this:
int daysUntilBill = 0;
int billingDay = 4;
DateTime today = DateTime.Today;
if (billingDay > today.Day) {
daysUntilBill = billingDay - today.Day;
} else {
int daysLeftInMonth = DateTime.DaysInMonth(today.Year, today.Month) - today.Day;
daysUntilBill = billingDay + daysLeftInMonth;
}
or slightly more concise
int daysUntilBill = (billingDay >= today.Day)
? billingDay - today.Day
: billingDay + DateTime.DaysInMonth(today.Year, today.Month) - today.Day;
This properly handles the year ending too, since it doesn't try to wrap around.
First you need to determine if the current date is on or before the billing day and if it is just subtract the current day of the month. Otherwise you have to determine the next billing date in the following month.
public int DaysToNextBill(int billingDay)
{
var today = DateTime.Today;
if(today.Day <= billingDay)
return billingDay - today.Day;
var nextMonth = today.AddMonth(1);
var nextBillingDate = new DateTime(nextMonth.Year, nextMonth.Month, billingDay)
return (nextBillingDate - today).Days;
}
The only thing left to deal with is if billingDay is greater than the number of days in the current or following month.
I have been trying to find the 5th week date of a day in a month like 5th week Monday date, 5th week Tue date, Wed... and so on based on the date from the same month. This date could belong to any week of same month.
I tried like
DateTime MonthEventDate=05/01/2016; //Date format in dd/MM/yyyy format
DayOfWeek EventDay="Sunday"; //For Example i want to find 5th Sunday in January Month, but days too will change everytime based on user selection
string SelectedWeek="5"; //Here i'm getting the week in which i need to find the given date i.e, 5th Monday or Tuesday & so on
if (SelectedWeek == "5")
{
//Here i tried to add number of days to my initial day to find 5th day date, but every time its returning next month value
MonthEventDate = MonthEventDate.AddDays((EventDay < MonthEventDate.DayOfWeek ? 31 : 28) + EventDay - MonthEventDate.DayOfWeek);
}
I know the logic is wrong but i want to get date of 5th day of the week, and if that day is not present, return 0. Looking for some guidance
Note: Here Month will change based on User Input, so how to return Date of fifth day, if it exist in the given month
This should give you the 5th day (if there is one) ...
DateTime dayInMonth = DateTime.Now;
DayOfWeek dayToFind = DayOfWeek.Friday;
var fifth= Enumerable.Range(1, DateTime.DaysInMonth(dayInMonth.Year, dayInMonth.Month))
.Select(day => new DateTime(dayInMonth.Year, dayInMonth.Month, day))
.Where(day => day.DayOfWeek == dayToFind)
.Skip(4)
.FirstOrDefault();
Extending #Soner Gönül's answer. In input you put required day of week, required month and required year. On output you get date of same day of week in fifth weeks, or null
public DateTime? FifthDay(DayOfWeek dayOfWeek, byte monthNum, int year)
{
if (monthNum > 12 || monthNum < 1)
{
throw new Exception("Month value should be between 1 and 12");
}
var searchDate = new DateTime(year, monthNum, 1);
var weekDay = searchDate.DayOfWeek;
if (weekDay == dayOfWeek)
{
searchDate = searchDate.AddDays(28);
}
for (DateTime d = searchDate; d < d.AddDays(7); d = d.AddDays(1))
{
if (d.DayOfWeek == dayOfWeek)
{
searchDate = searchDate.AddDays(28);
break;
}
}
if (searchDate.Month == monthNum)
return searchDate;
return null;
}
You can use a simple math like this (no validations included)
static DateTime? FindDate(int year, int month, DayOfWeek dayOfWeek, int weekOfMonth = 5)
{
var baseDate = new DateTime(year, month, 1);
int firstDateOffset = ((int)dayOfWeek - (int)baseDate.DayOfWeek + 7) % 7;
var date = baseDate.AddDays(firstDateOffset + 7 * (weekOfMonth - 1));
return date.Month == month ? date : (DateTime?)null;
}
I think the code is self explanatory. The only trick that probably needs explanation is the line
int firstDateOffset = ((int)dayOfWeek - (int)baseDate.DayOfWeek + 7) % 7;
which handles the case when let say the month starts in Friday and you asked for Monday, and is a short equivalent of
int firstDateOffset = (int)dayOfWeek - (int)baseDate.DayOfWeek;
if (firstDateOffset < 0) firstDateOffset += 7;
Usage in your example
var monthEventDate = FindDate(2016, 1, DayOfWeek.Sunday, 5);
You can refer this demo code
int requiredDay = 5; //Day number i.e 0-6(Sunday to SaturDay)
DateTime day = new DateTime(2016, 1, 1); //Month,year,Date
if (DateTime.DaysInMonth(day.Year, day.Month) > 28)
{
//Get the first day name of the month
int firstMonthDay = (int)day.DayOfWeek;
int offset=0;
//Number of days from the first day for the required day
if (firstMonthDay <= requiredDay)
offset = requiredDay - firstMonthDay;
else
offset = 7 - firstMonthDay + requiredDay;
//
DateTime firstoccurence = day.AddDays((double)offset);
DateTime fifthOccurence = firstoccurence.AddDays(28);
if (fifthOccurence.Month == firstoccurence.Month)
MessageBox.Show(fifthOccurence.ToString());
else
MessageBox.Show("No 5th Occurence for this day");
}
I want to calculate the number of weeks within a month.
The first week of January 2014 starting from the first Monday is the 6th. So, January has 4 weeks.
The first week of March 2014 starting from the first Monday is the 3rd. So, March has 5 weeks.
I want to know how many weeks there are in a month counting from the first Monday, not the first day.
How do I do this?
I have this code but it is used to get week number of the month for specific dates.
public int GetWeekNumberOfMonth(DateTime date)
{
date = date.Date;
DateTime firstMonthDay = new DateTime(date.Year, date.Month, 1);
DateTime firstMonthMonday = firstMonthDay.AddDays((DayOfWeek.Monday + 7 - firstMonthDay.DayOfWeek) % 7);
if (firstMonthMonday > date)
{
firstMonthDay = firstMonthDay.AddMonths(-1);
firstMonthMonday = firstMonthDay.AddDays((DayOfWeek.Monday + 7 - firstMonthDay.DayOfWeek) % 7);
}
return (date - firstMonthMonday).Days / 7 + 1;
}
Try this:
Get the number of days in the current month, and find the first day. For each day in the month, see if the day is a Monday, if so, increment the value.
public static int MondaysInMonth(DateTime thisMonth)
{
int mondays = 0;
int month = thisMonth.Month;
int year = thisMonth.Year;
int daysThisMonth = DateTime.DaysInMonth(year, month);
DateTime beginingOfThisMonth = new DateTime(year, month, 1);
for (int i = 0; i < daysThisMonth; i++)
if (beginingOfThisMonth.AddDays(i).DayOfWeek == DayOfWeek.Monday)
mondays++;
return mondays;
}
You can use it like this with the current date:
Console.WriteLine(MondaysInMonth(DateTime.Now));
Output:
4
or with any month you choose:
Console.WriteLine(MondaysInMonth(new DateTime(year, month, 1)))
Just correction to Cyral code :
i must start from 0 as he is using AddDays method .
Reason :the above example returns 5 for NOV and 4 for DEC which is wrong..
Edited code :
public static int MondaysInMonth(DateTime thisMonth)
{
int mondays = 0;
int month = thisMonth.Month;
int year = thisMonth.Year;
int daysThisMonth = DateTime.DaysInMonth(year, month);
DateTime beginingOfThisMonth = new DateTime(year, month, 1);
for (int i = 0; i < daysThisMonth; i++)
if (beginingOfThisMonth.AddDays(i).DayOfWeek == DayOfWeek.Monday)
mondays++;
return mondays;
}
I tried to use that code, but in some cases it didn't work. So I found this code on MSDN.
public static int MondaysInMonth(this DateTime time)
{
//extract the month
int daysInMonth = DateTime.DaysInMonth(time.Year, time.Month);
var firstOfMonth = new DateTime(time.Year, time.Month, 1);
//days of week starts by default as Sunday = 0
var firstDayOfMonth = (int)firstOfMonth.DayOfWeek;
var weeksInMonth = (int)Math.Ceiling((firstDayOfMonth + daysInMonth) / 7.0);
return weeksInMonth;
}
I created it like a extension method, so I can use like that:
var dateTimeNow = DateTime.Now;
var weeks = dateTimeNow.MondaysInMonth();
The faster method without looping
private static double GetDaysCount(DateTime sampleDate, int DayOfWeekToMatch)
{
int FirstDayOfMonth = (int)(new DateTime(sampleDate.Year, sampleDate.Month, 1).DayOfWeek);
int FirstOccurrenceOn = 0;
if (FirstDayOfMonth < DayOfWeekToMatch)
FirstOccurrenceOn = DayOfWeekToMatch - FirstDayOfMonth + 1;
else
FirstOccurrenceOn = (7 - FirstDayOfMonth) + DayOfWeekToMatch + 1;
int totalDays = DateTime.DaysInMonth(sampleDate.Year, sampleDate.Month);
return Math.Ceiling((totalDays - FirstOccurrenceOn) / 7.0f);
}
This question already has answers here:
How do I calculate someone's age based on a DateTime type birthday?
(74 answers)
Closed 6 years ago.
How can I calculate date difference between two dates in years?
For example: (Datetime.Now.Today() - 11/03/2007) in years.
I have written an implementation that properly works with dates exactly one year apart.
However, it does not gracefully handle negative timespans, unlike the other algorithm. It also doesn't use its own date arithmetic, instead relying upon the standard library for that.
So without further ado, here is the code:
DateTime zeroTime = new DateTime(1, 1, 1);
DateTime a = new DateTime(2007, 1, 1);
DateTime b = new DateTime(2008, 1, 1);
TimeSpan span = b - a;
// Because we start at year 1 for the Gregorian
// calendar, we must subtract a year here.
int years = (zeroTime + span).Year - 1;
// 1, where my other algorithm resulted in 0.
Console.WriteLine("Yrs elapsed: " + years);
Use:
int Years(DateTime start, DateTime end)
{
return (end.Year - start.Year - 1) +
(((end.Month > start.Month) ||
((end.Month == start.Month) && (end.Day >= start.Day))) ? 1 : 0);
}
We had to code a check to establish if the difference between two dates, a start and end date was greater than 2 years.
Thanks to the tips above it was done as follows:
DateTime StartDate = Convert.ToDateTime("01/01/2012");
DateTime EndDate = Convert.ToDateTime("01/01/2014");
DateTime TwoYears = StartDate.AddYears(2);
if EndDate > TwoYears .....
If you need it for knowing someone's age for trivial reasons then Timespan is OK but if you need for calculating superannuation, long term deposits or anything else for financial, scientific or legal purposes then I'm afraid Timespan won't be accurate enough because Timespan assumes that every year has the same number of days, same # of hours and same # of seconds).
In reality the length of some years will vary (for different reasons that are outside the scope of this answer). To get around Timespan's limitation then you can mimic what Excel does which is:
public int GetDifferenceInYears(DateTime startDate, DateTime endDate)
{
//Excel documentation says "COMPLETE calendar years in between dates"
int years = endDate.Year - startDate.Year;
if (startDate.Month == endDate.Month &&// if the start month and the end month are the same
endDate.Day < startDate.Day// AND the end day is less than the start day
|| endDate.Month < startDate.Month)// OR if the end month is less than the start month
{
years--;
}
return years;
}
var totalYears =
(DateTime.Today - new DateTime(2007, 03, 11)).TotalDays
/ 365.2425;
Average days from Wikipedia/Leap_year.
int Age = new DateTime((DateTime.Now - BirthDateTime).Ticks).Year;
To calculate the elapsed years (age), the result will be minus one.
var timeSpan = DateTime.Now - birthDateTime;
int age = new DateTime(timeSpan.Ticks).Year - 1;
Here is a neat trick which lets the system deal with leap years automagically. It gives an accurate answer for all date combinations.
DateTime dt1 = new DateTime(1987, 9, 23, 13, 12, 12, 0);
DateTime dt2 = new DateTime(2007, 6, 15, 16, 25, 46, 0);
DateTime tmp = dt1;
int years = -1;
while (tmp < dt2)
{
years++;
tmp = tmp.AddYears(1);
}
Console.WriteLine("{0}", years);
It's unclear how you want to handle fractional years, but perhaps like this:
DateTime now = DateTime.Now;
DateTime origin = new DateTime(2007, 11, 3);
int calendar_years = now.Year - origin.Year;
int whole_years = calendar_years - ((now.AddYears(-calendar_years) >= origin)? 0: 1);
int another_method = calendar_years - ((now.Month - origin.Month) * 32 >= origin.Day - now.Day)? 0: 1);
I implemented an extension method to get the number of years between two dates, rounded by whole months.
/// <summary>
/// Gets the total number of years between two dates, rounded to whole months.
/// Examples:
/// 2011-12-14, 2012-12-15 returns 1.
/// 2011-12-14, 2012-12-14 returns 1.
/// 2011-12-14, 2012-12-13 returns 0,9167.
/// </summary>
/// <param name="start">
/// Stardate of time period
/// </param>
/// <param name="end">
/// Enddate of time period
/// </param>
/// <returns>
/// Total Years between the two days
/// </returns>
public static double DifferenceTotalYears(this DateTime start, DateTime end)
{
// Get difference in total months.
int months = ((end.Year - start.Year) * 12) + (end.Month - start.Month);
// substract 1 month if end month is not completed
if (end.Day < start.Day)
{
months--;
}
double totalyears = months / 12d;
return totalyears;
}
public string GetAgeText(DateTime birthDate)
{
const double ApproxDaysPerMonth = 30.4375;
const double ApproxDaysPerYear = 365.25;
int iDays = (DateTime.Now - birthDate).Days;
int iYear = (int)(iDays / ApproxDaysPerYear);
iDays -= (int)(iYear * ApproxDaysPerYear);
int iMonths = (int)(iDays / ApproxDaysPerMonth);
iDays -= (int)(iMonths * ApproxDaysPerMonth);
return string.Format("{0} år, {1} måneder, {2} dage", iYear, iMonths, iDays);
}
I found this at TimeSpan for years, months and days:
DateTime target_dob = THE_DOB;
DateTime true_age = DateTime.MinValue + ((TimeSpan)(DateTime.Now - target_dob )); // Minimum value as 1/1/1
int yr = true_age.Year - 1;
If you're dealing with months and years you need something that knows how many days each month has and which years are leap years.
Enter the Gregorian Calendar (and other culture-specific Calendar implementations).
While Calendar doesn't provide methods to directly calculate the difference between two points in time, it does have methods such as
DateTime AddWeeks(DateTime time, int weeks)
DateTime AddMonths(DateTime time, int months)
DateTime AddYears(DateTime time, int years)
DateTime musteriDogum = new DateTime(dogumYil, dogumAy, dogumGun);
int additionalDays = ((DateTime.Now.Year - dogumYil) / 4); //Count of the years with 366 days
int extraDays = additionalDays + ((DateTime.Now.Year % 4 == 0 || musteriDogum.Year % 4 == 0) ? 1 : 0); //We add 1 if this year or year inserted has 366 days
int yearsOld = ((DateTime.Now - musteriDogum).Days - extraDays ) / 365; // Now we extract these extra days from total days and we can divide to 365
Works perfect:
internal static int GetDifferenceInYears(DateTime startDate)
{
int finalResult = 0;
const int DaysInYear = 365;
DateTime endDate = DateTime.Now;
TimeSpan timeSpan = endDate - startDate;
if (timeSpan.TotalDays > 365)
{
finalResult = (int)Math.Round((timeSpan.TotalDays / DaysInYear), MidpointRounding.ToEven);
}
return finalResult;
}
Simple solution:
public int getYearDiff(DateTime startDate, DateTime endDate){
int y = Year(endDate) - Year(startDate);
int startMonth = Month(startDate);
int endMonth = Month(endDate);
if (endMonth < startMonth)
return y - 1;
if (endMonth > startMonth)
return y;
return (Day(endDate) < Day(startDate) ? y - 1 : y);
}
This is the best code to calculate year and month difference:
DateTime firstDate = DateTime.Parse("1/31/2019");
DateTime secondDate = DateTime.Parse("2/1/2016");
int totalYears = firstDate.Year - secondDate.Year;
int totalMonths = 0;
if (firstDate.Month > secondDate.Month)
totalMonths = firstDate.Month - secondDate.Month;
else if (firstDate.Month < secondDate.Month)
{
totalYears -= 1;
int monthDifference = secondDate.Month - firstDate.Month;
totalMonths = 12 - monthDifference;
}
if ((firstDate.Day - secondDate.Day) == 30)
{
totalMonths += 1;
if (totalMonths % 12 == 0)
{
totalYears += 1;
totalMonths = 0;
}
}
Maybe this will be helpful for answering the question: Count of days in given year,
new DateTime(anyDate.Year, 12, 31).DayOfYear //will include leap years too
Regarding DateTime.DayOfYear Property.
The following is based off Dana's simple code which produces the correct answer in most cases. But it did not take in to account less than a year between dates. So here is the code that I use to produce consistent results:
public static int DateDiffYears(DateTime startDate, DateTime endDate)
{
var yr = endDate.Year - startDate.Year - 1 +
(endDate.Month >= startDate.Month && endDate.Day >= startDate.Day ? 1 : 0);
return yr < 0 ? 0 : yr;
}
As the title says, given the year and the week number, how do I get the month number?
edit: if a week crosses two months, I want the month the first day of the week is in.
edit(2): This is how I get the week number:
CultureInfo.CurrentCulture.Calendar.GetWeekOfYear(DateTime.Now, CalendarWeekRule.FirstDay, DayOfWeek.Monday);
I'm just trying to do the reverse.
If you assume that the first day of your definition of week is the same day as the 1st day of the year, then this will work:
int year = 2000;
int week = 9;
int month = new DateTime(year, 1, 1).AddDays(7 * (week - 1)).Month;
Obviously, a true answer would depend on how you define the first day of the week, and how you define how a week falls into a month when it overlaps more than one.
This is what I ended up doing:
static int GetMonth(int Year, int Week)
{
DateTime tDt = new DateTime(Year, 1, 1);
tDt.AddDays((Week - 1) * 7);
for (int i = 0; i <= 365; ++i)
{
int tWeek = CultureInfo.CurrentCulture.Calendar.GetWeekOfYear(
tDt,
CalendarWeekRule.FirstDay,
DayOfWeek.Monday);
if (tWeek == Week)
return tDt.Month;
tDt = tDt.AddDays(1);
}
return 0;
}
I would have preferred something simpler, but it works :)
Wouldn't it also depend on the day of the week?
this should be able to help
public int getMonth(int weekNum, int year)
{
DateTime Current = new DateTime(year, 1, 1);
System.DayOfWeek StartDOW = Current.DayOfWeek;
int DayOfYear = (weekNum * 7) - 6; //1st day of the week
if (StartDOW != System.DayOfWeek.Sunday) //means that last week of last year's month
{
Current = Current.AddDays(7 - (int)Current.DayOfWeek);
}
return Current.AddDays(DayOfYear).Month;
}
Another problem you could face is that most years do not start at the beginning of a week, which shifts everything.
Assumptions:
Sunday is the first day of the week.
Partial week still counts as week 1
Outputs beginning and ending month as integer array.
public int[] getMonth(int weekNum, int year)
{
DateTime StartYear = new DateTime(year, 1, 1);
System.DayOfWeek StartDOW = StartYear.DayOfWeek;
DateTime DayOfYearWeekStart = default(DateTime);
DateTime DayOfYearWeekEnd = default(DateTime);
int x = 0;
if ((StartDOW == System.DayOfWeek.Sunday)) {
DayOfYearWeekStart = StartYear.AddDays((weekNum - 1) * 7);
DayOfYearWeekEnd = DayOfYearWeekStart.AddDays(6);
} else {
for (x = 0; x <= 7; x += 1) {
if (StartYear.AddDays(x).DayOfWeek == DayOfWeek.Sunday) {
break; // TODO: might not be correct. Was : Exit For
}
}
if (weekNum == 1) {
DayOfYearWeekStart = StartYear;
DayOfYearWeekEnd = StartYear.AddDays(x - 1);
} else if (weekNum > 1) {
DayOfYearWeekStart = StartYear.AddDays(((weekNum - 2) * 7) + x);
DayOfYearWeekEnd = DayOfYearWeekStart.AddDays(6);
}
}
int[] Month = new int[2];
Month[0] = DayOfYearWeekStart.Month;
Month[1] = DayOfYearWeekEnd.Month;
return Month;
}
You cant. You need at least the day on which the 1st week starts (or when the week starts), to get an accurate answer.
You cant. A week may start in one month and end in another.
I think you're assuming that a "week" is any group of 7 sequential days. It isn't. Given Year(2008), Week(5), you could be in either January or Febuary, depending on when your "week" starts.
In .NET 3.0 and later you can use the ISOWeek-Class.
public static int MonthOfFirstDay(int year, int week)
{
return ISOWeek.ToDateTime(year, week, DayOfWeek.Monday).Month;
}
Note that the year might not fit, as the first week of a year can already start in end of December the year before. For instance the first week of 2020 started on Monday 2019-12-30.
// Calculate the week number according to ISO 8601
public static int Iso8601WeekNumber(DateTime dt)
{
return CultureInfo.CurrentCulture.Calendar.GetWeekOfYear(dt, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
}
// ...
DateTime dt = DateTime.Now;
// Calculate the WeekOfMonth according to ISO 8601
int weekOfMonth = Iso8601WeekNumber(dt) - Iso8601WeekNumber(dt.AddDays(1 - dt.Day)) + 1;