Asked  6 Months ago    Answers:  5   Viewed   36 times

I have the following code to do this, but how can I do it better? Right now I think it's better than nested loops, but it starts to get Perl-one-linerish when you have a generator in a list comprehension.

day_count = (end_date - start_date).days + 1
for single_date in [d for d in (start_date + timedelta(n) for n in range(day_count)) if d <= end_date]:
    print strftime("%Y-%m-%d", single_date.timetuple())

Notes

  • I'm not actually using this to print. That's just for demo purposes.
  • The start_date and end_date variables are datetime.date objects because I don't need the timestamps. (They're going to be used to generate a report).

Sample Output

For a start date of 2009-05-30 and an end date of 2009-06-09:

2009-05-30
2009-05-31
2009-06-01
2009-06-02
2009-06-03
2009-06-04
2009-06-05
2009-06-06
2009-06-07
2009-06-08
2009-06-09

 Answers

77

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().

Tuesday, June 1, 2021
 
DilbertDave
answered 6 Months ago
53

Marginally better...

base = datetime.datetime.today()
date_list = [base - datetime.timedelta(days=x) for x in range(numdays)]
Tuesday, June 1, 2021
 
exxed
answered 6 Months ago
90

According https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html Z has special meaning:

Z       zone-offset

If you want to escape Z quote Z with ':

yyyy-MM-dd'T'HH:mm:ss.SSS'Z'

For example:

java.time.LocalDateTime date = java.time.LocalDateTime.now();
java.time.format.DateTimeFormatter formatter = java.time.format.DateTimeFormatter
                .ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
java.lang.String text = date.format(formatter);
System.out.println(text);

prints

2016-06-11T18:39:41.962Z
Saturday, July 31, 2021
 
Gishantha Darshana
answered 4 Months ago
15

Using an IntervalIndex, which is new in Pandas 0.20.0. This looks to still be in the experimental phase though, so other solutions may be more reliable.

# Get the 'id' column indexed by the 'start'/'end' intervals.
s = pd.Series(df_b['id'].values, pd.IntervalIndex.from_arrays(df_b['start'], df_b['end']))

# Map based on the date of df_a.
df_a['id'] = df_a['date'].map(s)

The resulting output:

        date values  id
0 2017-05-16      x  34
1 2017-04-12      Y  32

Alternatively, if you don't mind altering the index of df_b, you could just directly convert to an IntervalIndex on it:

# Create an IntervalIndex on df_b.
df_b = df_b.set_index(['start', 'end'])
df_b.index = pd.IntervalIndex.from_tuples(df_b.index)

# Map based on the date of df_a.
df_a['id'] = df_a['date'].map(df_b['id'])
Sunday, August 15, 2021
 
truemp
answered 4 Months ago
73

This should do it:

from datetime import datetime 

def is_third_friday(s):
    d = datetime.strptime(s, '%b %d, %Y')
    return d.weekday() == 4 and 15 <= d.day <= 21

Test:

print is_third_friday('Jan 18, 2013')  # True
print is_third_friday('Feb 22, 2013')  # False
print is_third_friday('Jun 21, 2013')  # True
print is_third_friday('Sep 20, 2013')  # True
Monday, September 6, 2021
 
Aaron
answered 3 Months ago
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 :  
Share