Iterate Every Month with Date Objects

Iterate every month with date objects

I have added following method to Date class:

class Date
def all_months_until to
from = self
from, to = to, from if from > to
m = Date.new from.year, from.month
result = []
while m <= to
result << m
m >>= 1
end

result
end
end

You use it like:

>> t = Date.today
=> #<Date: 2009-11-12 (4910295/2,0,2299161)>
>> t.all_months_until(t+100)
=> [#<Date: 2009-11-01 (4910273/2,0,2299161)>, #<Date: 2009-12-01 (4910333/2,0,2299161)>, #<Date: 2010-01-01 (4910395/2,0,2299161)>, #<Date: 2010-02-01 (4910457/2,0,2299161)>]

Ok, so, more rubyish approach IMHO would be something along:

class Month<Date
def succ
self >> 1
end
end

and

>> t = Month.today
=> #<Month: 2009-11-13 (4910297/2,0,2299161)>
>> (t..t+100).to_a
=> [#<Month: 2009-11-13 (4910297/2,0,2299161)>, #<Month: 2009-12-13 (4910357/2,0,2299161)>, #<Month: 2010-01-13 (4910419/2,0,2299161)>, #<Month: 2010-02-13 (4910481/2,0,2299161)>]

But you would need to be careful to use first days of month (or implement such logic in Month)...

Iterating through a range of dates in Python

Why are there two nested iterations? For me it produces the same list of data with only one iteration:

for single_date in (start_date + timedelta(n) for n in range(day_count)):
print ...

And no list gets stored, only one generator is iterated over. Also the "if" in the generator seems to be unnecessary.

After all, a linear sequence should only require one iterator, not two.

Update after discussion with John Machin:

Maybe the most elegant solution is using a generator function to completely hide/abstract the iteration over the range of dates:

from datetime import date, timedelta

def daterange(start_date, end_date):
for n in range(int((end_date - start_date).days)):
yield start_date + timedelta(n)

start_date = date(2013, 1, 1)
end_date = date(2015, 6, 2)
for single_date in daterange(start_date, end_date):
print(single_date.strftime("%Y-%m-%d"))

NB: For consistency with the built-in range() function this iteration stops before reaching the end_date. So for inclusive iteration use the next day, as you would with range().

Python: Iterate over all days in a month

The calendar module is designed to display calendars. You are better off using calendar.monthlen in combination with datetime.date itself to get your iterator, if you are looking for something straightforward:

def date_iter(year, month):
for i in range(1, calendar.monthlen(year, month) + 1):
yield date(year, month, i)

for d in date_iter(2019, 12):
print(d)

You can of course write the whole thing as a one-liner:

for d in (date(2019, 12, i) for i in range(1, calendar.monthlen(2019, 12) + 1)):
print(d)

The monthlen attribute appears to be a public, but undocumented attribute of calendar in Python 3.7. It is analogous to the second element of monthrange, so you can replace it with monthrange(year, month)[1] in the code above.

Is there a way to iterate over specific month or week

There is no time.Date object defined in the standard library. Only time.Time object. There's also no way to range loop them, but looping them manually is quite simple:

// set the starting date (in any way you wish)
start, err := time.Parse("2006-1-2", "2016-4-1")
// handle error

// set d to starting date and keep adding 1 day to it as long as month doesn't change
for d := start; d.Month() == start.Month(); d = d.AddDate(0, 0, 1) {
// do stuff with d
}

Loop through a date range with JavaScript

Here's a way to do it by making use of the way adding one day causes the date to roll over to the next month if necessary, and without messing around with milliseconds. Daylight savings aren't an issue either.

var now = new Date();
var daysOfYear = [];
for (var d = new Date(2012, 0, 1); d <= now; d.setDate(d.getDate() + 1)) {
daysOfYear.push(new Date(d));
}

Note that if you want to store the date, you'll need to make a new one (as above with new Date(d)), or else you'll end up with every stored date being the final value of d in the loop.

Iterate through Calendar Month Beginning/End

Use pandas.tseries.offsets.MonthEnd

Ex:

from pandas.tseries.offsets import MonthEnd

for beg in pd.date_range('2014-01-01', '2014-06-30', freq='MS'):
print(beg.strftime("%Y-%m-%d"), (beg + MonthEnd(1)).strftime("%Y-%m-%d"))

Output:

2014-01-01 2014-01-31
2014-02-01 2014-02-28
2014-03-01 2014-03-31
2014-04-01 2014-04-30
2014-05-01 2014-05-31
2014-06-01 2014-06-30

Loop through date range with a monthly step

There are lots of way to do it, but trying to keep it similar to what you have, removing things that are not needed, and using a Dictionary instead:

Sub test()
Dim sDate As String
Dim dict As Object
Dim Cell As Range

Set dict = CreateObject("Scripting.Dictionary")

For Each Cell In Range("F2", Range("F2").End(xlDown))
sDate = Format$(Range("D" & Cell.Row), "mm/yyyy")
If Not dict.Exists(sDate) Then
dict.Add sDate, 1
Debug.Print sDate
End If
Next

Debug.Print "Total: " & dict.Count

End Sub

There are things you can do with the Dictionary afterwards if your Debug.Print is not exactly what you needed.

How to loop through months in Javascript

The problem is within your date.setDate(date.getMonth() + 1) code as the MDN documentation states the setDate function sets the day to the specified Date object. Therefore, it's not behaving as you had intended.

To better illustrate the problem, the date variable is initialized as Mon Oct 13 2014 00:00:00 GMT-0400 (Eastern Daylight Time). When you call date.getMonth() it returns 9 indicating the 10th month in the calendar year; so incrementing the value by 1 results in setting the day of the date variable to 10.

On the next iteration, the month hasn't changed, so the code re-executes date.getMonth() which returns 9 again, so on and so on.
This unexpected behavior continues to repeat endlessly as the while condition is never satisfied.

The code should be updated to use setMonth instead.

How to iterate through range of Dates in Java?

Well, you could do something like this using Java 8's time-API, for this problem specifically java.time.LocalDate (or the equivalent Joda Time classes for Java 7 and older)

for (LocalDate date = startDate; date.isBefore(endDate); date = date.plusDays(1))
{
...
}

I would thoroughly recommend using java.time (or Joda Time) over the built-in Date/Calendar classes.

How do I loop through a date range?

Well, you'll need to loop over them one way or the other. I prefer defining a method like this:

public IEnumerable<DateTime> EachDay(DateTime from, DateTime thru)
{
for(var day = from.Date; day.Date <= thru.Date; day = day.AddDays(1))
yield return day;
}

Then you can use it like this:

foreach (DateTime day in EachDay(StartDate, EndDate))
// print it or whatever

In this manner you could hit every other day, every third day, only weekdays, etc. For example, to return every third day starting with the "start" date, you could just call AddDays(3) in the loop instead of AddDays(1).



Related Topics



Leave a reply



Submit