Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
sdispater committed Feb 20, 2017
2 parents b7da758 + d29cd2f commit 76a8fe0
Show file tree
Hide file tree
Showing 18 changed files with 451 additions and 171 deletions.
16 changes: 15 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
# Change Log

[Unreleased]

### Added

- Added the `keep_time` keyword argument to `next()`/`previous()` methods to keep time information.

### Changed

- Greatly improved `diff()` performance.
- Improved `diff_for_humans()` method to display more intuitive strings on edge cases.
- Formatting (with f-strings or `format()`) will now use the configured formatter.


## [1.0.2]

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


[Unreleased]: https://github.com/sdispater/pendulum/compare/1.0.2...master

[Unreleased]: https://github.com/sdispater/pendulum/compare/1.0.2...develop
[1.0.2]: https://github.com/sdispater/pendulum/releases/tag/1.0.2
[1.0.1]: https://github.com/sdispater/pendulum/releases/tag/1.0.1
[1.0.0]: https://github.com/sdispater/pendulum/releases/tag/1.0.0
Expand Down
21 changes: 21 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
# http://www.opensource.org/licenses/MIT-license
# Copyright (c) 2015 Sébastien Eustace

PENDULUM_RELEASE := $$(sed -n -E "s/VERSION = '(.+)'/\1/p" pendulum/version.py)

# lists all available targets
list:
@sh -c "$(MAKE) -p no_targets__ | \
Expand All @@ -21,21 +23,40 @@ setup: setup-python
test:
@py.test --cov=pendulum --cov-config .coveragerc tests/ -sq

release: tar wheels_x64 cp_wheels_x64 wheels_i686 cp_wheels_i686 wheel

publish:
@python -m twine upload dist/pendulum-$(PENDULUM_RELEASE)*

tar:
python setup.py sdist --formats=gztar

wheel:
@pip wheel --no-index --no-deps --wheel-dir dist dist/pendulum-$(PENDULUM_RELEASE).tar.gz

wheels_x64: clean_wheels build_wheels_x64

wheels_i686: clean_wheels build_wheels_i686

build_wheels_x64:
rm -rf wheelhouse/
docker pull quay.io/pypa/manylinux1_x86_64
docker run --rm -v `pwd`:/io quay.io/pypa/manylinux1_x86_64 /io/build-wheels.sh

build_wheels_i686:
rm -rf wheelhouse/
docker pull quay.io/pypa/manylinux1_i686
docker run --rm -v `pwd`:/io quay.io/pypa/manylinux1_i686 /io/build-wheels.sh

clean_wheels:
rm -rf wheelhouse/

cp_wheels_x64:
cp wheelhouse/*manylinux1_x86_64.whl dist/

cp_wheels_i686:
cp wheelhouse/*manylinux1_i686.whl dist/

upload_wheels_x64:
@for f in wheelhouse/*manylinux1_x86_64.whl ; do \
echo "Upload $$f" ; \
Expand Down
8 changes: 6 additions & 2 deletions docs/_docs/modifiers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ It moves your instance to the middle date between itself and the provided Pendul
dt.start_of('decade')
'2010-01-01 00:00:00'
dt = Pendulum.create(2012, 1, 31, 12, 0, 0)
dt = pendulum.create(2012, 1, 31, 12, 0, 0)
dt.end_of('decade')
'2019-01-31 23:59:59'
Expand Down Expand Up @@ -76,9 +76,11 @@ It moves your instance to the middle date between itself and the provided Pendul
dt.day_of_week == pendulum.WEDNESDAY
True
dt = Pendulum.create(2012, 1, 1, 12, 0, 0)
dt = pendulum.create(2012, 1, 1, 12, 0, 0)
dt.next()
'2012-01-08 00:00:00'
dt.next(keep_time=True)
'2012-01-08T12:00:00+00:00'
dt = pendulum.create(2012, 1, 31, 12, 0, 0)
dt.previous(pendulum.WEDNESDAY)
Expand All @@ -89,6 +91,8 @@ It moves your instance to the middle date between itself and the provided Pendul
dt = pendulum.create(2012, 1, 1, 12, 0, 0)
dt.previous()
'2011-12-25 00:00:00'
dt.previous(keep_time=True)
'2011-12-25 12:00:00'
start = pendulum.create(2014, 1, 1, 0, 0, 0)
end = pendulum.create(2014, 1, 30, 0, 0, 0)
Expand Down
60 changes: 16 additions & 44 deletions pendulum/date.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from dateutil.relativedelta import relativedelta

from .period import Period
from .formatting.difference_formatter import DifferenceFormatter
from .mixins.default import TranslatableMixin, FormattableMixing, TestableMixin
from .constants import (
DAYS_PER_WEEK, YEARS_PER_DECADE, YEARS_PER_CENTURY,
Expand Down Expand Up @@ -44,6 +45,8 @@ class Date(TranslatableMixin, FormattableMixing, TestableMixin, date):

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

_diff_formatter = None

@classmethod
def instance(cls, dt):
"""
Expand Down Expand Up @@ -609,6 +612,18 @@ def __sub__(self, other):

# DIFFERENCES

@property
def diff_formatter(self):
"""
Returns a DifferenceFormatter instance.
:rtype: DifferenceFormatter
"""
if not self.__class__._diff_formatter:
self.__class__._diff_formatter = DifferenceFormatter(self.__class__.translator())

return self.__class__._diff_formatter

def diff(self, dt=None, abs=True):
"""
Returns the difference between two Date objects as a Period.
Expand Down Expand Up @@ -655,50 +670,7 @@ def diff_for_humans(self, other=None, absolute=False, locale=None):
:rtype: str
"""
is_now = other is None

if is_now:
other = self.today()

diff = self.diff(other)

if diff.years > 0:
unit = 'year'
count = diff.years
elif diff.months > 0:
unit = 'month'
count = diff.months
elif diff.weeks > 0:
unit = 'week'
count = diff.weeks
elif diff.days > 0:
unit = 'day'
count = diff.days
else:
unit = 'second'
count = diff.seconds

if count == 0:
count = 1

time = self.translator().transchoice(unit, count, {'count': count}, locale=locale)

if absolute:
return time

is_future = diff.invert

if is_now:
trans_id = 'from_now' if is_future else 'ago'
else:
trans_id = 'after' if is_future else 'before'

# Some langs have special pluralization for past and future tense
try_key_exists = '%s_%s' % (unit, trans_id)
if try_key_exists != self.translator().transchoice(try_key_exists, count, locale=locale):
time = self.translator().transchoice(try_key_exists, count, {'count': count}, locale=locale)

return self.translator().trans(trans_id, {'time': time}, locale=locale)
return self.diff_formatter.diff_for_humans(self, other, absolute, locale)

# MODIFIERS

Expand Down
96 changes: 96 additions & 0 deletions pendulum/formatting/difference_formatter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# -*- coding: utf-8 -*-

from ..translator import Translator


class DifferenceFormatter(object):
"""
Handles formatting differences in text.
"""

def __init__(self, translator=Translator()):
self._translator = translator

def diff_for_humans(self, date, other=None, absolute=False, locale=None):
"""
Get the difference in a human readable format.
:param date: The datetime to start with.
:type date: pendulum.Date or pendulum.Pendulum
:param other: The datetime to compare against (defaults to now).
:type other: pendulum.Date or pendulum.Pendulum or None
:param absolute: Removes time difference modifiers ago, after, etc
:type absolute: bool
:param locale: The locale to use
:type locale: str or None
:rtype: str
"""
is_now = other is None

if is_now:
if hasattr(date, 'now'):
other = date.now(date.timezone)
else:
other = date.today()

diff = date.diff(other)

count = diff.remaining_seconds
unit = 'second'

if diff.years > 0:
unit = 'year'
count = diff.years

if diff.months > 6:
count += 1
elif diff.months == 11 and (diff.weeks * 7 + diff.remaining_days) > 15:
unit = 'year'
count = 1
elif diff.months > 0:
unit = 'month'
count = diff.months

if (diff.weeks * 7 + diff.remaining_days) > 28:
count += 1
elif diff.weeks > 0:
unit = 'week'
count = diff.weeks

if diff.remaining_days > 3:
count += 1
elif diff.days > 0:
unit = 'day'
count = diff.days
elif diff.hours > 0:
unit = 'hour'
count = diff.hours
elif diff.minutes > 0:
unit = 'minute'
count = diff.minutes

if count == 0:
count = 1

time = self._translator.transchoice(unit, count, {'count': count}, locale=locale)

if absolute:
return time

is_future = diff.invert

if is_now:
trans_id = 'from_now' if is_future else 'ago'
else:
trans_id = 'after' if is_future else 'before'

# Some langs have special pluralization for past and future tense
try_key_exists = '%s_%s' % (unit, trans_id)
if try_key_exists != self._translator.transchoice(try_key_exists, count, locale=locale):
time = self._translator.transchoice(try_key_exists, count, {'count': count}, locale=locale)

return self._translator.trans(trans_id, {'time': time}, locale=locale)
Loading

0 comments on commit 76a8fe0

Please sign in to comment.