Skip to content

Commit 76a8fe0

Browse files
committed
Merge branch 'develop'
2 parents b7da758 + d29cd2f commit 76a8fe0

File tree

18 files changed

+451
-171
lines changed

18 files changed

+451
-171
lines changed

CHANGELOG.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,18 @@
11
# Change Log
22

3+
[Unreleased]
4+
5+
### Added
6+
7+
- Added the `keep_time` keyword argument to `next()`/`previous()` methods to keep time information.
8+
9+
### Changed
10+
11+
- Greatly improved `diff()` performance.
12+
- Improved `diff_for_humans()` method to display more intuitive strings on edge cases.
13+
- Formatting (with f-strings or `format()`) will now use the configured formatter.
14+
15+
316
## [1.0.2]
417

518
### Changed
@@ -319,7 +332,8 @@ This version causes major breaking API changes to simplify it and making it more
319332
Initial release
320333

321334

322-
[Unreleased]: https://github.com/sdispater/pendulum/compare/1.0.2...master
335+
336+
[Unreleased]: https://github.com/sdispater/pendulum/compare/1.0.2...develop
323337
[1.0.2]: https://github.com/sdispater/pendulum/releases/tag/1.0.2
324338
[1.0.1]: https://github.com/sdispater/pendulum/releases/tag/1.0.1
325339
[1.0.0]: https://github.com/sdispater/pendulum/releases/tag/1.0.0

Makefile

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
# http://www.opensource.org/licenses/MIT-license
66
# Copyright (c) 2015 Sébastien Eustace
77

8+
PENDULUM_RELEASE := $$(sed -n -E "s/VERSION = '(.+)'/\1/p" pendulum/version.py)
9+
810
# lists all available targets
911
list:
1012
@sh -c "$(MAKE) -p no_targets__ | \
@@ -21,21 +23,40 @@ setup: setup-python
2123
test:
2224
@py.test --cov=pendulum --cov-config .coveragerc tests/ -sq
2325

26+
release: tar wheels_x64 cp_wheels_x64 wheels_i686 cp_wheels_i686 wheel
27+
28+
publish:
29+
@python -m twine upload dist/pendulum-$(PENDULUM_RELEASE)*
30+
31+
tar:
32+
python setup.py sdist --formats=gztar
33+
34+
wheel:
35+
@pip wheel --no-index --no-deps --wheel-dir dist dist/pendulum-$(PENDULUM_RELEASE).tar.gz
36+
2437
wheels_x64: clean_wheels build_wheels_x64
2538

2639
wheels_i686: clean_wheels build_wheels_i686
2740

2841
build_wheels_x64:
42+
rm -rf wheelhouse/
2943
docker pull quay.io/pypa/manylinux1_x86_64
3044
docker run --rm -v `pwd`:/io quay.io/pypa/manylinux1_x86_64 /io/build-wheels.sh
3145

3246
build_wheels_i686:
47+
rm -rf wheelhouse/
3348
docker pull quay.io/pypa/manylinux1_i686
3449
docker run --rm -v `pwd`:/io quay.io/pypa/manylinux1_i686 /io/build-wheels.sh
3550

3651
clean_wheels:
3752
rm -rf wheelhouse/
3853

54+
cp_wheels_x64:
55+
cp wheelhouse/*manylinux1_x86_64.whl dist/
56+
57+
cp_wheels_i686:
58+
cp wheelhouse/*manylinux1_i686.whl dist/
59+
3960
upload_wheels_x64:
4061
@for f in wheelhouse/*manylinux1_x86_64.whl ; do \
4162
echo "Upload $$f" ; \

docs/_docs/modifiers.rst

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ It moves your instance to the middle date between itself and the provided Pendul
4040
dt.start_of('decade')
4141
'2010-01-01 00:00:00'
4242
43-
dt = Pendulum.create(2012, 1, 31, 12, 0, 0)
43+
dt = pendulum.create(2012, 1, 31, 12, 0, 0)
4444
dt.end_of('decade')
4545
'2019-01-31 23:59:59'
4646
@@ -76,9 +76,11 @@ It moves your instance to the middle date between itself and the provided Pendul
7676
dt.day_of_week == pendulum.WEDNESDAY
7777
True
7878
79-
dt = Pendulum.create(2012, 1, 1, 12, 0, 0)
79+
dt = pendulum.create(2012, 1, 1, 12, 0, 0)
8080
dt.next()
8181
'2012-01-08 00:00:00'
82+
dt.next(keep_time=True)
83+
'2012-01-08T12:00:00+00:00'
8284
8385
dt = pendulum.create(2012, 1, 31, 12, 0, 0)
8486
dt.previous(pendulum.WEDNESDAY)
@@ -89,6 +91,8 @@ It moves your instance to the middle date between itself and the provided Pendul
8991
dt = pendulum.create(2012, 1, 1, 12, 0, 0)
9092
dt.previous()
9193
'2011-12-25 00:00:00'
94+
dt.previous(keep_time=True)
95+
'2011-12-25 12:00:00'
9296
9397
start = pendulum.create(2014, 1, 1, 0, 0, 0)
9498
end = pendulum.create(2014, 1, 30, 0, 0, 0)

pendulum/date.py

Lines changed: 16 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from dateutil.relativedelta import relativedelta
99

1010
from .period import Period
11+
from .formatting.difference_formatter import DifferenceFormatter
1112
from .mixins.default import TranslatableMixin, FormattableMixing, TestableMixin
1213
from .constants import (
1314
DAYS_PER_WEEK, YEARS_PER_DECADE, YEARS_PER_CENTURY,
@@ -44,6 +45,8 @@ class Date(TranslatableMixin, FormattableMixing, TestableMixin, date):
4445

4546
_MODIFIERS_VALID_UNITS = ['day', 'week', 'month', 'year', 'decade', 'century']
4647

48+
_diff_formatter = None
49+
4750
@classmethod
4851
def instance(cls, dt):
4952
"""
@@ -609,6 +612,18 @@ def __sub__(self, other):
609612

610613
# DIFFERENCES
611614

615+
@property
616+
def diff_formatter(self):
617+
"""
618+
Returns a DifferenceFormatter instance.
619+
620+
:rtype: DifferenceFormatter
621+
"""
622+
if not self.__class__._diff_formatter:
623+
self.__class__._diff_formatter = DifferenceFormatter(self.__class__.translator())
624+
625+
return self.__class__._diff_formatter
626+
612627
def diff(self, dt=None, abs=True):
613628
"""
614629
Returns the difference between two Date objects as a Period.
@@ -655,50 +670,7 @@ def diff_for_humans(self, other=None, absolute=False, locale=None):
655670
656671
:rtype: str
657672
"""
658-
is_now = other is None
659-
660-
if is_now:
661-
other = self.today()
662-
663-
diff = self.diff(other)
664-
665-
if diff.years > 0:
666-
unit = 'year'
667-
count = diff.years
668-
elif diff.months > 0:
669-
unit = 'month'
670-
count = diff.months
671-
elif diff.weeks > 0:
672-
unit = 'week'
673-
count = diff.weeks
674-
elif diff.days > 0:
675-
unit = 'day'
676-
count = diff.days
677-
else:
678-
unit = 'second'
679-
count = diff.seconds
680-
681-
if count == 0:
682-
count = 1
683-
684-
time = self.translator().transchoice(unit, count, {'count': count}, locale=locale)
685-
686-
if absolute:
687-
return time
688-
689-
is_future = diff.invert
690-
691-
if is_now:
692-
trans_id = 'from_now' if is_future else 'ago'
693-
else:
694-
trans_id = 'after' if is_future else 'before'
695-
696-
# Some langs have special pluralization for past and future tense
697-
try_key_exists = '%s_%s' % (unit, trans_id)
698-
if try_key_exists != self.translator().transchoice(try_key_exists, count, locale=locale):
699-
time = self.translator().transchoice(try_key_exists, count, {'count': count}, locale=locale)
700-
701-
return self.translator().trans(trans_id, {'time': time}, locale=locale)
673+
return self.diff_formatter.diff_for_humans(self, other, absolute, locale)
702674

703675
# MODIFIERS
704676

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
# -*- coding: utf-8 -*-
2+
3+
from ..translator import Translator
4+
5+
6+
class DifferenceFormatter(object):
7+
"""
8+
Handles formatting differences in text.
9+
"""
10+
11+
def __init__(self, translator=Translator()):
12+
self._translator = translator
13+
14+
def diff_for_humans(self, date, other=None, absolute=False, locale=None):
15+
"""
16+
Get the difference in a human readable format.
17+
18+
:param date: The datetime to start with.
19+
:type date: pendulum.Date or pendulum.Pendulum
20+
21+
:param other: The datetime to compare against (defaults to now).
22+
:type other: pendulum.Date or pendulum.Pendulum or None
23+
24+
:param absolute: Removes time difference modifiers ago, after, etc
25+
:type absolute: bool
26+
27+
:param locale: The locale to use
28+
:type locale: str or None
29+
30+
:rtype: str
31+
"""
32+
is_now = other is None
33+
34+
if is_now:
35+
if hasattr(date, 'now'):
36+
other = date.now(date.timezone)
37+
else:
38+
other = date.today()
39+
40+
diff = date.diff(other)
41+
42+
count = diff.remaining_seconds
43+
unit = 'second'
44+
45+
if diff.years > 0:
46+
unit = 'year'
47+
count = diff.years
48+
49+
if diff.months > 6:
50+
count += 1
51+
elif diff.months == 11 and (diff.weeks * 7 + diff.remaining_days) > 15:
52+
unit = 'year'
53+
count = 1
54+
elif diff.months > 0:
55+
unit = 'month'
56+
count = diff.months
57+
58+
if (diff.weeks * 7 + diff.remaining_days) > 28:
59+
count += 1
60+
elif diff.weeks > 0:
61+
unit = 'week'
62+
count = diff.weeks
63+
64+
if diff.remaining_days > 3:
65+
count += 1
66+
elif diff.days > 0:
67+
unit = 'day'
68+
count = diff.days
69+
elif diff.hours > 0:
70+
unit = 'hour'
71+
count = diff.hours
72+
elif diff.minutes > 0:
73+
unit = 'minute'
74+
count = diff.minutes
75+
76+
if count == 0:
77+
count = 1
78+
79+
time = self._translator.transchoice(unit, count, {'count': count}, locale=locale)
80+
81+
if absolute:
82+
return time
83+
84+
is_future = diff.invert
85+
86+
if is_now:
87+
trans_id = 'from_now' if is_future else 'ago'
88+
else:
89+
trans_id = 'after' if is_future else 'before'
90+
91+
# Some langs have special pluralization for past and future tense
92+
try_key_exists = '%s_%s' % (unit, trans_id)
93+
if try_key_exists != self._translator.transchoice(try_key_exists, count, locale=locale):
94+
time = self._translator.transchoice(try_key_exists, count, {'count': count}, locale=locale)
95+
96+
return self._translator.trans(trans_id, {'time': time}, locale=locale)

0 commit comments

Comments
 (0)