Asked  10 Months ago    Answers:  5   Viewed   1 times

Can anyone find a constant in the .NET framework that defines the number of days in a week (7)?

DateTime.DaysInAWeek // Something like this???

Of course I can define my own, but I'd rather not if it's somewhere in there already.

Update:

I am looking for this because I need to allow the user to select a week (by date, rather than week number) from a list in a DropDownList.

 Answers

2

You could probably use System.Globalization.DateTimeFormatInfo.CurrentInfo.DayNames.Length.

Sunday, August 22, 2021
 
abyss.7
 
3

Nope, doing a simple comparison looks good to me:

return dateToCheck >= startDate && dateToCheck < endDate;

Things to think about though:

  • DateTime is a somewhat odd type in terms of time zones. It could be UTC, it could be "local", it could be ambiguous. Make sure you're comparing apples with apples, as it were.
  • Consider whether your start and end points should be inclusive or exclusive. I've made the code above treat it as an inclusive lower bound and an exclusive upper bound.
Sunday, June 6, 2021
 
e_i_pi
 
5

OADate is similar to Julian Dates, but uses a different starting point (December 30, 1899 vs. January 1, 4713 BC), and a different 'new day' point. Julian Dates consider noon to be the beginning of a new day, OADates use the modern definition, midnight.

The Julian Date of midnight, December 30, 1899 is 2415018.5. This method should give you the proper values:

public static double ToJulianDate(this DateTime date)
{
    return date.ToOADate() + 2415018.5;
}

As for the algorithm:

  • if (Month < 3) ...: To make the magic numbers work our right, they're putting February at the 'end' of the year.
  • (153 * Month - 457) / 5: Wow, that's some serious magic numbers.
    • Normally, the number of days in each month is 31 28 31 30 31 30 31 31 30 31 30 31, but after that adjustment in the if statement, it becomes 31 30 31 30 31 31 30 31 30 31 31 28. Or, subtract 30 and you end up with 1 0 1 0 1 1 0 1 0 1 1 -2. They're creating that pattern of 1s and 0s by doing that division in integer space.
    • Re-written to floating point, it would be (int)(30.6 * Month - 91.4). 30.6 is the average number of days per month, excluding February (30.63 repeating, to be exact). 91.4 is almost the number of days in 3 average non-February months. (30.6 * 3 is 91.8).
    • So, let's remove the 30, and just focus on that 0.6 days. If we multiply it by the number of months, and then truncate to an integer, we'll get a pattern of 0s and 1s.
      • 0.6 * 0 = 0.0 -> 0
      • 0.6 * 1 = 0.6 -> 0 (difference of 0)
      • 0.6 * 2 = 1.2 -> 1 (difference of 1)
      • 0.6 * 3 = 1.8 -> 1 (difference of 0)
      • 0.6 * 4 = 2.4 -> 2 (difference of 1)
      • 0.6 * 5 = 3.0 -> 3 (difference of 1)
      • 0.6 * 6 = 3.6 -> 3 (difference of 0)
      • 0.6 * 7 = 4.2 -> 4 (difference of 1)
      • 0.6 * 8 = 4.8 -> 4 (difference of 0)
    • See that pattern of differences in the right? That's the same pattern in the list above, the number of days in each month minus 30. The subtraction of 91.8 would compensate for the number of days in the first three months, that were moved to the 'end' of the year, and adjusting it by 0.4 moves the successive differences of 1 (0.6 * 4 and 0.6 * 5 in the above table) to align with the adjacent months that are 31 days.
    • Since February is now at the 'end' of the year, we don't need to deal with its length. It could be 45 days long (46 on a leap year), and the only thing that would have to change is the constant for the number of days in a year, 365.
    • Note that this relies on the pattern of 30 and 31 month days. If we had two months in a row that were 30 days, this would not be possible.
  • 365 * Year: Days per year
  • (Year / 4) - (Year / 100) + (Year / 400): Plus one leap day every 4 years, minus one every 100, plus one every 400.
  • + 1721119: This is the Julian Date of March 2nd, 1 BC. Since we moved the 'start' of the calendar from January to March, we use this as our offset, rather than January 1st. Since there is no year zero, 1 BC gets the integer value 0. As for why March 2nd instead of March 1st, I'm guessing that's because that whole month calculation was still a little off at the end. If the original writer had used - 462 instead of - 457 (- 92.4 instead of - 91.4 in floating point math), then the offset would have been to March 1st.
Wednesday, June 9, 2021
 
4

This is the implementation from ActiveSupport (a little adapted):

COMMON_YEAR_DAYS_IN_MONTH = [nil, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]

def days_in_month(month, year = Time.now.year)
   return 29 if month == 2 && Date.gregorian_leap?(year)
   COMMON_YEAR_DAYS_IN_MONTH[month]
end
Sunday, August 8, 2021
 
5

Calculate the duration in days:

from datetime import date

campaign_start_date = date(2017, 9, 7)
campaign_end_date = date(2017, 10, 6)
duration = (campaign_end_date-campaign_start_date).days
print campaign_start_date, campaign_end_date, duration 

Some hints for further calculations:

import calendar

campaign_end_month_start = campaign_end_date.replace(day=1)
days_in_month_campaign_end = (campaign_end_date - campaign_end_month_start).days + 1

range_startmonth = calendar.monthrange(campaign_start_date.year, campaign_start_date.month)
campaign_start_month_ends = campaign_start_date.replace(day=range_startmonth[1])

days_in_month_campaign_begins = (campaign_start_month_ends - campaign_start_date).days

This way you can calculate the number of days in each month of the campaign (keep in mind to check if campaign_end_date is in another month than campaign_start_date

For calculations you can also access the fields of a date, e.g.

campaign_start_date.day
campaign_start_date.month
campaign_start_date.year

To calculate the number of involved month in your campaign and to get a list of the month to calculate the duration per month you can use this (based on the answer of m.antkowicz in Python: get all months in range?). It's important to set the day to 1 (current = current.replace(day=1)) before and inside the loop, otherwise you skip a month when your startdate is 31st of a month and the next month is shorter than 31 days or if you have a longer period:

from datetime import date, datetime, timedelta    
current = campaign_start_date
result = [current]

current = current.replace(day=1)
while current <= campaign_end_date:
    current += timedelta(days=32)
    current = current.replace(day=1)
    result.append(datetime(current.year, current.month, 1))

print result, len(result)

which prints (when you use current.strftime('%Y-%m-%d'):

['2017-09-07', '2017-10-01', '2017-11-01'] 3

now you can loop over the result list and calculate the number of days per months:

durations= []
for curr in result:
    curr_range = calendar.monthrange(curr.year, curr.month)
    curr_duration = (curr_range[1] - curr.day)+1
    if (curr.month < campaign_end_date.month):
        durations.append(curr_duration)
    else:
        durations.append(campaign_end_date.day)

print durations

which gives you the desired "No:of days in Month x" as a list:

[24, 31, 6]

Friday, December 3, 2021
 
Packy
 
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :