Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/pendulum/date.py: 35%

272 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2023-06-07 06:35 +0000

1from __future__ import absolute_import 

2from __future__ import division 

3 

4import calendar 

5import math 

6 

7from datetime import date 

8from datetime import timedelta 

9 

10import pendulum 

11 

12from .constants import FRIDAY 

13from .constants import MONDAY 

14from .constants import MONTHS_PER_YEAR 

15from .constants import SATURDAY 

16from .constants import SUNDAY 

17from .constants import THURSDAY 

18from .constants import TUESDAY 

19from .constants import WEDNESDAY 

20from .constants import YEARS_PER_CENTURY 

21from .constants import YEARS_PER_DECADE 

22from .exceptions import PendulumException 

23from .helpers import add_duration 

24from .mixins.default import FormattableMixin 

25from .period import Period 

26 

27 

28class Date(FormattableMixin, date): 

29 

30 # Names of days of the week 

31 _days = { 

32 SUNDAY: "Sunday", 

33 MONDAY: "Monday", 

34 TUESDAY: "Tuesday", 

35 WEDNESDAY: "Wednesday", 

36 THURSDAY: "Thursday", 

37 FRIDAY: "Friday", 

38 SATURDAY: "Saturday", 

39 } 

40 

41 _MODIFIERS_VALID_UNITS = ["day", "week", "month", "year", "decade", "century"] 

42 

43 # Getters/Setters 

44 

45 def set(self, year=None, month=None, day=None): 

46 return self.replace(year=year, month=month, day=day) 

47 

48 @property 

49 def day_of_week(self): 

50 """ 

51 Returns the day of the week (0-6). 

52 

53 :rtype: int 

54 """ 

55 return self.isoweekday() % 7 

56 

57 @property 

58 def day_of_year(self): 

59 """ 

60 Returns the day of the year (1-366). 

61 

62 :rtype: int 

63 """ 

64 k = 1 if self.is_leap_year() else 2 

65 

66 return (275 * self.month) // 9 - k * ((self.month + 9) // 12) + self.day - 30 

67 

68 @property 

69 def week_of_year(self): 

70 return self.isocalendar()[1] 

71 

72 @property 

73 def days_in_month(self): 

74 return calendar.monthrange(self.year, self.month)[1] 

75 

76 @property 

77 def week_of_month(self): 

78 first_day_of_month = self.replace(day=1) 

79 

80 return self.week_of_year - first_day_of_month.week_of_year + 1 

81 

82 @property 

83 def age(self): 

84 return self.diff(abs=False).in_years() 

85 

86 @property 

87 def quarter(self): 

88 return int(math.ceil(self.month / 3)) 

89 

90 # String Formatting 

91 

92 def to_date_string(self): 

93 """ 

94 Format the instance as date. 

95 

96 :rtype: str 

97 """ 

98 return self.strftime("%Y-%m-%d") 

99 

100 def to_formatted_date_string(self): 

101 """ 

102 Format the instance as a readable date. 

103 

104 :rtype: str 

105 """ 

106 return self.strftime("%b %d, %Y") 

107 

108 def __repr__(self): 

109 return ( 

110 "{klass}(" 

111 "{year}, {month}, {day}" 

112 ")".format( 

113 klass=self.__class__.__name__, 

114 year=self.year, 

115 month=self.month, 

116 day=self.day, 

117 ) 

118 ) 

119 

120 # COMPARISONS 

121 

122 def closest(self, dt1, dt2): 

123 """ 

124 Get the closest date from the instance. 

125 

126 :type dt1: Date or date 

127 :type dt2: Date or date 

128 

129 :rtype: Date 

130 """ 

131 dt1 = self.__class__(dt1.year, dt1.month, dt1.day) 

132 dt2 = self.__class__(dt2.year, dt2.month, dt2.day) 

133 

134 if self.diff(dt1).in_seconds() < self.diff(dt2).in_seconds(): 

135 return dt1 

136 

137 return dt2 

138 

139 def farthest(self, dt1, dt2): 

140 """ 

141 Get the farthest date from the instance. 

142 

143 :type dt1: Date or date 

144 :type dt2: Date or date 

145 

146 :rtype: Date 

147 """ 

148 dt1 = self.__class__(dt1.year, dt1.month, dt1.day) 

149 dt2 = self.__class__(dt2.year, dt2.month, dt2.day) 

150 

151 if self.diff(dt1).in_seconds() > self.diff(dt2).in_seconds(): 

152 return dt1 

153 

154 return dt2 

155 

156 def is_future(self): 

157 """ 

158 Determines if the instance is in the future, ie. greater than now. 

159 

160 :rtype: bool 

161 """ 

162 return self > self.today() 

163 

164 def is_past(self): 

165 """ 

166 Determines if the instance is in the past, ie. less than now. 

167 

168 :rtype: bool 

169 """ 

170 return self < self.today() 

171 

172 def is_leap_year(self): 

173 """ 

174 Determines if the instance is a leap year. 

175 

176 :rtype: bool 

177 """ 

178 return calendar.isleap(self.year) 

179 

180 def is_long_year(self): 

181 """ 

182 Determines if the instance is a long year 

183 

184 See link `<https://en.wikipedia.org/wiki/ISO_8601#Week_dates>`_ 

185 

186 :rtype: bool 

187 """ 

188 return Date(self.year, 12, 28).isocalendar()[1] == 53 

189 

190 def is_same_day(self, dt): 

191 """ 

192 Checks if the passed in date is the same day as the instance current day. 

193 

194 :type dt: Date or date 

195 

196 :rtype: bool 

197 """ 

198 return self == dt 

199 

200 def is_anniversary(self, dt=None): 

201 """ 

202 Check if its the anniversary. 

203 

204 Compares the date/month values of the two dates. 

205 

206 :rtype: bool 

207 """ 

208 if dt is None: 

209 dt = Date.today() 

210 

211 instance = self.__class__(dt.year, dt.month, dt.day) 

212 

213 return (self.month, self.day) == (instance.month, instance.day) 

214 

215 # the additional method for checking if today is the anniversary day 

216 # the alias is provided to start using a new name and keep the backward compatibility 

217 # the old name can be completely replaced with the new in one of the future versions 

218 is_birthday = is_anniversary 

219 

220 # ADDITIONS AND SUBSTRACTIONS 

221 

222 def add(self, years=0, months=0, weeks=0, days=0): 

223 """ 

224 Add duration to the instance. 

225 

226 :param years: The number of years 

227 :type years: int 

228 

229 :param months: The number of months 

230 :type months: int 

231 

232 :param weeks: The number of weeks 

233 :type weeks: int 

234 

235 :param days: The number of days 

236 :type days: int 

237 

238 :rtype: Date 

239 """ 

240 dt = add_duration( 

241 date(self.year, self.month, self.day), 

242 years=years, 

243 months=months, 

244 weeks=weeks, 

245 days=days, 

246 ) 

247 

248 return self.__class__(dt.year, dt.month, dt.day) 

249 

250 def subtract(self, years=0, months=0, weeks=0, days=0): 

251 """ 

252 Remove duration from the instance. 

253 

254 :param years: The number of years 

255 :type years: int 

256 

257 :param months: The number of months 

258 :type months: int 

259 

260 :param weeks: The number of weeks 

261 :type weeks: int 

262 

263 :param days: The number of days 

264 :type days: int 

265 

266 :rtype: Date 

267 """ 

268 return self.add(years=-years, months=-months, weeks=-weeks, days=-days) 

269 

270 def _add_timedelta(self, delta): 

271 """ 

272 Add timedelta duration to the instance. 

273 

274 :param delta: The timedelta instance 

275 :type delta: pendulum.Duration or datetime.timedelta 

276 

277 :rtype: Date 

278 """ 

279 if isinstance(delta, pendulum.Duration): 

280 return self.add( 

281 years=delta.years, 

282 months=delta.months, 

283 weeks=delta.weeks, 

284 days=delta.remaining_days, 

285 ) 

286 

287 return self.add(days=delta.days) 

288 

289 def _subtract_timedelta(self, delta): 

290 """ 

291 Remove timedelta duration from the instance. 

292 

293 :param delta: The timedelta instance 

294 :type delta: pendulum.Duration or datetime.timedelta 

295 

296 :rtype: Date 

297 """ 

298 if isinstance(delta, pendulum.Duration): 

299 return self.subtract( 

300 years=delta.years, 

301 months=delta.months, 

302 weeks=delta.weeks, 

303 days=delta.remaining_days, 

304 ) 

305 

306 return self.subtract(days=delta.days) 

307 

308 def __add__(self, other): 

309 if not isinstance(other, timedelta): 

310 return NotImplemented 

311 

312 return self._add_timedelta(other) 

313 

314 def __sub__(self, other): 

315 if isinstance(other, timedelta): 

316 return self._subtract_timedelta(other) 

317 

318 if not isinstance(other, date): 

319 return NotImplemented 

320 

321 dt = self.__class__(other.year, other.month, other.day) 

322 

323 return dt.diff(self, False) 

324 

325 # DIFFERENCES 

326 

327 def diff(self, dt=None, abs=True): 

328 """ 

329 Returns the difference between two Date objects as a Period. 

330 

331 :type dt: Date or None 

332 

333 :param abs: Whether to return an absolute interval or not 

334 :type abs: bool 

335 

336 :rtype: Period 

337 """ 

338 if dt is None: 

339 dt = self.today() 

340 

341 return Period(self, Date(dt.year, dt.month, dt.day), absolute=abs) 

342 

343 def diff_for_humans(self, other=None, absolute=False, locale=None): 

344 """ 

345 Get the difference in a human readable format in the current locale. 

346 

347 When comparing a value in the past to default now: 

348 1 day ago 

349 5 months ago 

350 

351 When comparing a value in the future to default now: 

352 1 day from now 

353 5 months from now 

354 

355 When comparing a value in the past to another value: 

356 1 day before 

357 5 months before 

358 

359 When comparing a value in the future to another value: 

360 1 day after 

361 5 months after 

362 

363 :type other: Date 

364 

365 :param absolute: removes time difference modifiers ago, after, etc 

366 :type absolute: bool 

367 

368 :param locale: The locale to use for localization 

369 :type locale: str 

370 

371 :rtype: str 

372 """ 

373 is_now = other is None 

374 

375 if is_now: 

376 other = self.today() 

377 

378 diff = self.diff(other) 

379 

380 return pendulum.format_diff(diff, is_now, absolute, locale) 

381 

382 # MODIFIERS 

383 

384 def start_of(self, unit): 

385 """ 

386 Returns a copy of the instance with the time reset 

387 with the following rules: 

388 

389 * day: time to 00:00:00 

390 * week: date to first day of the week and time to 00:00:00 

391 * month: date to first day of the month and time to 00:00:00 

392 * year: date to first day of the year and time to 00:00:00 

393 * decade: date to first day of the decade and time to 00:00:00 

394 * century: date to first day of century and time to 00:00:00 

395 

396 :param unit: The unit to reset to 

397 :type unit: str 

398 

399 :rtype: Date 

400 """ 

401 if unit not in self._MODIFIERS_VALID_UNITS: 

402 raise ValueError('Invalid unit "{}" for start_of()'.format(unit)) 

403 

404 return getattr(self, "_start_of_{}".format(unit))() 

405 

406 def end_of(self, unit): 

407 """ 

408 Returns a copy of the instance with the time reset 

409 with the following rules: 

410 

411 * week: date to last day of the week 

412 * month: date to last day of the month 

413 * year: date to last day of the year 

414 * decade: date to last day of the decade 

415 * century: date to last day of century 

416 

417 :param unit: The unit to reset to 

418 :type unit: str 

419 

420 :rtype: Date 

421 """ 

422 if unit not in self._MODIFIERS_VALID_UNITS: 

423 raise ValueError('Invalid unit "%s" for end_of()' % unit) 

424 

425 return getattr(self, "_end_of_%s" % unit)() 

426 

427 def _start_of_day(self): 

428 """ 

429 Compatibility method. 

430 

431 :rtype: Date 

432 """ 

433 return self 

434 

435 def _end_of_day(self): 

436 """ 

437 Compatibility method 

438 

439 :rtype: Date 

440 """ 

441 return self 

442 

443 def _start_of_month(self): 

444 """ 

445 Reset the date to the first day of the month. 

446 

447 :rtype: Date 

448 """ 

449 return self.set(self.year, self.month, 1) 

450 

451 def _end_of_month(self): 

452 """ 

453 Reset the date to the last day of the month. 

454 

455 :rtype: Date 

456 """ 

457 return self.set(self.year, self.month, self.days_in_month) 

458 

459 def _start_of_year(self): 

460 """ 

461 Reset the date to the first day of the year. 

462 

463 :rtype: Date 

464 """ 

465 return self.set(self.year, 1, 1) 

466 

467 def _end_of_year(self): 

468 """ 

469 Reset the date to the last day of the year. 

470 

471 :rtype: Date 

472 """ 

473 return self.set(self.year, 12, 31) 

474 

475 def _start_of_decade(self): 

476 """ 

477 Reset the date to the first day of the decade. 

478 

479 :rtype: Date 

480 """ 

481 year = self.year - self.year % YEARS_PER_DECADE 

482 

483 return self.set(year, 1, 1) 

484 

485 def _end_of_decade(self): 

486 """ 

487 Reset the date to the last day of the decade. 

488 

489 :rtype: Date 

490 """ 

491 year = self.year - self.year % YEARS_PER_DECADE + YEARS_PER_DECADE - 1 

492 

493 return self.set(year, 12, 31) 

494 

495 def _start_of_century(self): 

496 """ 

497 Reset the date to the first day of the century. 

498 

499 :rtype: Date 

500 """ 

501 year = self.year - 1 - (self.year - 1) % YEARS_PER_CENTURY + 1 

502 

503 return self.set(year, 1, 1) 

504 

505 def _end_of_century(self): 

506 """ 

507 Reset the date to the last day of the century. 

508 

509 :rtype: Date 

510 """ 

511 year = self.year - 1 - (self.year - 1) % YEARS_PER_CENTURY + YEARS_PER_CENTURY 

512 

513 return self.set(year, 12, 31) 

514 

515 def _start_of_week(self): 

516 """ 

517 Reset the date to the first day of the week. 

518 

519 :rtype: Date 

520 """ 

521 dt = self 

522 

523 if self.day_of_week != pendulum._WEEK_STARTS_AT: 

524 dt = self.previous(pendulum._WEEK_STARTS_AT) 

525 

526 return dt.start_of("day") 

527 

528 def _end_of_week(self): 

529 """ 

530 Reset the date to the last day of the week. 

531 

532 :rtype: Date 

533 """ 

534 dt = self 

535 

536 if self.day_of_week != pendulum._WEEK_ENDS_AT: 

537 dt = self.next(pendulum._WEEK_ENDS_AT) 

538 

539 return dt.end_of("day") 

540 

541 def next(self, day_of_week=None): 

542 """ 

543 Modify to the next occurrence of a given day of the week. 

544 If no day_of_week is provided, modify to the next occurrence 

545 of the current day of the week. Use the supplied consts 

546 to indicate the desired day_of_week, ex. pendulum.MONDAY. 

547 

548 :param day_of_week: The next day of week to reset to. 

549 :type day_of_week: int or None 

550 

551 :rtype: Date 

552 """ 

553 if day_of_week is None: 

554 day_of_week = self.day_of_week 

555 

556 if day_of_week < SUNDAY or day_of_week > SATURDAY: 

557 raise ValueError("Invalid day of week") 

558 

559 dt = self.add(days=1) 

560 while dt.day_of_week != day_of_week: 

561 dt = dt.add(days=1) 

562 

563 return dt 

564 

565 def previous(self, day_of_week=None): 

566 """ 

567 Modify to the previous occurrence of a given day of the week. 

568 If no day_of_week is provided, modify to the previous occurrence 

569 of the current day of the week. Use the supplied consts 

570 to indicate the desired day_of_week, ex. pendulum.MONDAY. 

571 

572 :param day_of_week: The previous day of week to reset to. 

573 :type day_of_week: int or None 

574 

575 :rtype: Date 

576 """ 

577 if day_of_week is None: 

578 day_of_week = self.day_of_week 

579 

580 if day_of_week < SUNDAY or day_of_week > SATURDAY: 

581 raise ValueError("Invalid day of week") 

582 

583 dt = self.subtract(days=1) 

584 while dt.day_of_week != day_of_week: 

585 dt = dt.subtract(days=1) 

586 

587 return dt 

588 

589 def first_of(self, unit, day_of_week=None): 

590 """ 

591 Returns an instance set to the first occurrence 

592 of a given day of the week in the current unit. 

593 If no day_of_week is provided, modify to the first day of the unit. 

594 Use the supplied consts to indicate the desired day_of_week, ex. pendulum.MONDAY. 

595 

596 Supported units are month, quarter and year. 

597 

598 :param unit: The unit to use 

599 :type unit: str 

600 

601 :type day_of_week: int or None 

602 

603 :rtype: Date 

604 """ 

605 if unit not in ["month", "quarter", "year"]: 

606 raise ValueError('Invalid unit "{}" for first_of()'.format(unit)) 

607 

608 return getattr(self, "_first_of_{}".format(unit))(day_of_week) 

609 

610 def last_of(self, unit, day_of_week=None): 

611 """ 

612 Returns an instance set to the last occurrence 

613 of a given day of the week in the current unit. 

614 If no day_of_week is provided, modify to the last day of the unit. 

615 Use the supplied consts to indicate the desired day_of_week, ex. pendulum.MONDAY. 

616 

617 Supported units are month, quarter and year. 

618 

619 :param unit: The unit to use 

620 :type unit: str 

621 

622 :type day_of_week: int or None 

623 

624 :rtype: Date 

625 """ 

626 if unit not in ["month", "quarter", "year"]: 

627 raise ValueError('Invalid unit "{}" for first_of()'.format(unit)) 

628 

629 return getattr(self, "_last_of_{}".format(unit))(day_of_week) 

630 

631 def nth_of(self, unit, nth, day_of_week): 

632 """ 

633 Returns a new instance set to the given occurrence 

634 of a given day of the week in the current unit. 

635 If the calculated occurrence is outside the scope of the current unit, 

636 then raise an error. Use the supplied consts 

637 to indicate the desired day_of_week, ex. pendulum.MONDAY. 

638 

639 Supported units are month, quarter and year. 

640 

641 :param unit: The unit to use 

642 :type unit: str 

643 

644 :type nth: int 

645 

646 :type day_of_week: int or None 

647 

648 :rtype: Date 

649 """ 

650 if unit not in ["month", "quarter", "year"]: 

651 raise ValueError('Invalid unit "{}" for first_of()'.format(unit)) 

652 

653 dt = getattr(self, "_nth_of_{}".format(unit))(nth, day_of_week) 

654 if dt is False: 

655 raise PendulumException( 

656 "Unable to find occurence {} of {} in {}".format( 

657 nth, self._days[day_of_week], unit 

658 ) 

659 ) 

660 

661 return dt 

662 

663 def _first_of_month(self, day_of_week): 

664 """ 

665 Modify to the first occurrence of a given day of the week 

666 in the current month. If no day_of_week is provided, 

667 modify to the first day of the month. Use the supplied consts 

668 to indicate the desired day_of_week, ex. pendulum.MONDAY. 

669 

670 :type day_of_week: int 

671 

672 :rtype: Date 

673 """ 

674 dt = self 

675 

676 if day_of_week is None: 

677 return dt.set(day=1) 

678 

679 month = calendar.monthcalendar(dt.year, dt.month) 

680 

681 calendar_day = (day_of_week - 1) % 7 

682 

683 if month[0][calendar_day] > 0: 

684 day_of_month = month[0][calendar_day] 

685 else: 

686 day_of_month = month[1][calendar_day] 

687 

688 return dt.set(day=day_of_month) 

689 

690 def _last_of_month(self, day_of_week=None): 

691 """ 

692 Modify to the last occurrence of a given day of the week 

693 in the current month. If no day_of_week is provided, 

694 modify to the last day of the month. Use the supplied consts 

695 to indicate the desired day_of_week, ex. pendulum.MONDAY. 

696 

697 :type day_of_week: int or None 

698 

699 :rtype: Date 

700 """ 

701 dt = self 

702 

703 if day_of_week is None: 

704 return dt.set(day=self.days_in_month) 

705 

706 month = calendar.monthcalendar(dt.year, dt.month) 

707 

708 calendar_day = (day_of_week - 1) % 7 

709 

710 if month[-1][calendar_day] > 0: 

711 day_of_month = month[-1][calendar_day] 

712 else: 

713 day_of_month = month[-2][calendar_day] 

714 

715 return dt.set(day=day_of_month) 

716 

717 def _nth_of_month(self, nth, day_of_week): 

718 """ 

719 Modify to the given occurrence of a given day of the week 

720 in the current month. If the calculated occurrence is outside, 

721 the scope of the current month, then return False and no 

722 modifications are made. Use the supplied consts 

723 to indicate the desired day_of_week, ex. pendulum.MONDAY. 

724 

725 :type nth: int 

726 

727 :type day_of_week: int or None 

728 

729 :rtype: Date 

730 """ 

731 if nth == 1: 

732 return self.first_of("month", day_of_week) 

733 

734 dt = self.first_of("month") 

735 check = dt.format("YYYY-MM") 

736 for i in range(nth - (1 if dt.day_of_week == day_of_week else 0)): 

737 dt = dt.next(day_of_week) 

738 

739 if dt.format("YYYY-MM") == check: 

740 return self.set(day=dt.day) 

741 

742 return False 

743 

744 def _first_of_quarter(self, day_of_week=None): 

745 """ 

746 Modify to the first occurrence of a given day of the week 

747 in the current quarter. If no day_of_week is provided, 

748 modify to the first day of the quarter. Use the supplied consts 

749 to indicate the desired day_of_week, ex. pendulum.MONDAY. 

750 

751 :type day_of_week: int or None 

752 

753 :rtype: Date 

754 """ 

755 return self.set(self.year, self.quarter * 3 - 2, 1).first_of( 

756 "month", day_of_week 

757 ) 

758 

759 def _last_of_quarter(self, day_of_week=None): 

760 """ 

761 Modify to the last occurrence of a given day of the week 

762 in the current quarter. If no day_of_week is provided, 

763 modify to the last day of the quarter. Use the supplied consts 

764 to indicate the desired day_of_week, ex. pendulum.MONDAY. 

765 

766 :type day_of_week: int or None 

767 

768 :rtype: Date 

769 """ 

770 return self.set(self.year, self.quarter * 3, 1).last_of("month", day_of_week) 

771 

772 def _nth_of_quarter(self, nth, day_of_week): 

773 """ 

774 Modify to the given occurrence of a given day of the week 

775 in the current quarter. If the calculated occurrence is outside, 

776 the scope of the current quarter, then return False and no 

777 modifications are made. Use the supplied consts 

778 to indicate the desired day_of_week, ex. pendulum.MONDAY. 

779 

780 :type nth: int 

781 

782 :type day_of_week: int or None 

783 

784 :rtype: Date 

785 """ 

786 if nth == 1: 

787 return self.first_of("quarter", day_of_week) 

788 

789 dt = self.replace(self.year, self.quarter * 3, 1) 

790 last_month = dt.month 

791 year = dt.year 

792 dt = dt.first_of("quarter") 

793 for i in range(nth - (1 if dt.day_of_week == day_of_week else 0)): 

794 dt = dt.next(day_of_week) 

795 

796 if last_month < dt.month or year != dt.year: 

797 return False 

798 

799 return self.set(self.year, dt.month, dt.day) 

800 

801 def _first_of_year(self, day_of_week=None): 

802 """ 

803 Modify to the first occurrence of a given day of the week 

804 in the current year. If no day_of_week is provided, 

805 modify to the first day of the year. Use the supplied consts 

806 to indicate the desired day_of_week, ex. pendulum.MONDAY. 

807 

808 :type day_of_week: int or None 

809 

810 :rtype: Date 

811 """ 

812 return self.set(month=1).first_of("month", day_of_week) 

813 

814 def _last_of_year(self, day_of_week=None): 

815 """ 

816 Modify to the last occurrence of a given day of the week 

817 in the current year. If no day_of_week is provided, 

818 modify to the last day of the year. Use the supplied consts 

819 to indicate the desired day_of_week, ex. pendulum.MONDAY. 

820 

821 :type day_of_week: int or None 

822 

823 :rtype: Date 

824 """ 

825 return self.set(month=MONTHS_PER_YEAR).last_of("month", day_of_week) 

826 

827 def _nth_of_year(self, nth, day_of_week): 

828 """ 

829 Modify to the given occurrence of a given day of the week 

830 in the current year. If the calculated occurrence is outside, 

831 the scope of the current year, then return False and no 

832 modifications are made. Use the supplied consts 

833 to indicate the desired day_of_week, ex. pendulum.MONDAY. 

834 

835 :type nth: int 

836 

837 :type day_of_week: int or None 

838 

839 :rtype: Date 

840 """ 

841 if nth == 1: 

842 return self.first_of("year", day_of_week) 

843 

844 dt = self.first_of("year") 

845 year = dt.year 

846 for i in range(nth - (1 if dt.day_of_week == day_of_week else 0)): 

847 dt = dt.next(day_of_week) 

848 

849 if year != dt.year: 

850 return False 

851 

852 return self.set(self.year, dt.month, dt.day) 

853 

854 def average(self, dt=None): 

855 """ 

856 Modify the current instance to the average 

857 of a given instance (default now) and the current instance. 

858 

859 :type dt: Date or date 

860 

861 :rtype: Date 

862 """ 

863 if dt is None: 

864 dt = Date.today() 

865 

866 return self.add(days=int(self.diff(dt, False).in_days() / 2)) 

867 

868 # Native methods override 

869 

870 @classmethod 

871 def today(cls): 

872 return pendulum.today().date() 

873 

874 @classmethod 

875 def fromtimestamp(cls, t): 

876 dt = super(Date, cls).fromtimestamp(t) 

877 

878 return cls(dt.year, dt.month, dt.day) 

879 

880 @classmethod 

881 def fromordinal(cls, n): 

882 dt = super(Date, cls).fromordinal(n) 

883 

884 return cls(dt.year, dt.month, dt.day) 

885 

886 def replace(self, year=None, month=None, day=None): 

887 year = year if year is not None else self.year 

888 month = month if month is not None else self.month 

889 day = day if day is not None else self.day 

890 

891 return self.__class__(year, month, day)