Compare commits

...

35 Commits

Author SHA1 Message Date
Timo Furrer cc698817b4 release: 0.5.0 2018-05-26 15:19:57 +02:00
Timo Furrer 9964e9305e Merge pull request #154 from alxwrd/support-locales
Allow slang methods to change locale
2018-05-26 15:16:17 +02:00
Alex Ward d87236a30d update authors 2018-05-26 11:19:57 +01:00
Alex Ward d44a1dd2f6 add tracer tests for slang_ locales 2018-05-26 11:19:36 +01:00
Timo Furrer ed5d72b34c Merge pull request #155 from DavidMuller/patch-1
Add Example of Creating a MayaDT Using a Unix Time
2018-05-22 21:38:21 +02:00
David Muller 9c1e94f956 Add example that instantiates MayaDT w/ unix time 2018-05-22 10:45:01 -07:00
Alex Ward 6755968f69 remove unused calendar import 2018-05-22 09:57:32 +01:00
Alex Ward 3760af2c41 use pendulum and dateparser for slang_date 2018-05-21 22:37:31 +01:00
Alex Ward df09625e74 fix failing test 2018-05-15 22:56:28 +01:00
Alex Ward 2d848bd62a typo fix 2018-05-15 22:55:07 +01:00
Alex Ward a99cddf76f allow changing the locale for slang_time 2018-05-15 22:27:16 +01:00
Timo Furrer 1b432d6626 release: 0.4.3 2018-05-15 09:13:21 +02:00
Timo Furrer f09d6eec63 Split RFC3339 test 2018-05-15 09:13:01 +02:00
Timo Furrer 62a6283200 Merge pull request #150 from marcelstoer/patch-1
Fix RFC3339 representation
2018-05-15 09:08:52 +02:00
Marcel Stör 9ef43a29d9 Add RFC3339 unit test 2018-05-14 21:49:47 +02:00
Marcel Stör a2bff42439 Fix RFC3339 representation
Must be at most 1-digit millisecond.
2018-05-14 20:48:28 +02:00
Timo Furrer 5525beda31 release: 0.4.2 2018-05-10 17:25:04 +02:00
Timo Furrer eeb07d46db Merge pull request #152 from kennethreitz/feature/local-datetime
Implement method to get MayaDT instance as local timezone-aware datetime instance
2018-05-10 17:24:44 +02:00
Timo Furrer 4056d1a9aa Implement method to get MayaDT instance as local timezone-aware datetime instance 2018-05-10 17:22:35 +02:00
Timo Furrer 7a750a1cff release: 0.4.1 2018-05-10 11:32:54 +02:00
Timo Furrer bc06315abd Limit pendulum version to >=1.0 and <= 1.5.1
See https://github.com/sdispater/pendulum/issues/205
2018-05-10 11:32:32 +02:00
Timo Furrer 7cc767781a release: 0.4.0 2018-05-10 11:13:55 +02:00
Timo Furrer 8468dd2ead Fix subtracting MayaDT instances. Fixes #151 2018-05-10 11:04:16 +02:00
kennethreitz 046f005ca7 Update README.rst 2018-05-08 08:05:07 -04:00
kennethreitz cd0b2300d7 Merge pull request #128 from azban/patch-1
readme: add artist attribution
2018-05-08 08:04:05 -04:00
Timo Furrer d3ddb39d9d Merge pull request #144 from kennethreitz/feature/cleanup-pipenv-use
Refactor pipenv usage according to semi-official best practices.
2018-05-08 08:53:31 +02:00
Timo Furrer 3c8fe4478c Merge pull request #147 from alxwrd/fix-when-weekday-names
.when with weekdays and prefer_past
2018-04-17 17:58:27 +02:00
Alex Ward a0983132bb update .when docstring 2018-04-16 12:20:14 +01:00
Alex Ward 9612d70707 update .when tests to use new prefer_dates_from param 2018-04-16 12:06:12 +01:00
Alex Ward 363fae1aaf update .when to use prefer_dates_from to align with dateparser 2018-04-16 11:39:16 +01:00
Alex Ward be2cd96132 add more options to .when pefer_past param 2018-04-15 19:22:56 +01:00
Alex Ward 771a2b6ce2 add tests around weekday names 2018-04-15 17:31:06 +01:00
Timo Furrer 8e644f655a Merge pull request #145 from vlcinsky/pendulum_ver
fix `pendulum>=1.0` in setup.py (was missing version)
2018-04-05 10:17:55 +02:00
Jan Vlcinsky 6903f6eb63 fix pendulum>=1.0 in setup.py (was missing version)
Assuming, that when Pipfile declares such rule, it shall be also in
setup.py.
2018-04-05 00:50:53 +02:00
azban b05ca8707c readme: add artist attribution 2018-03-21 10:50:24 -07:00
6 changed files with 156 additions and 30 deletions
+1
View File
@@ -24,3 +24,4 @@ In chronological order:
- Evan Mattiza <emattiza@gmail.com> (`@emattiza <https://github.com/emattiza>`_)
- Dima Spivak <dima@spivak.ch> (`@dimaspivak <https://github.com/dimaspivak>`_)
- Tom Barron <tusculum@gmail.com> (`@dtbarron <https://github.com/tbarron>`_)
- Alex Ward <alxwrd@gmail.com> (`@alxwrd <https://github.com/alxwrd>`_)
+8
View File
@@ -22,6 +22,10 @@ Maya is mostly built around the headaches and use-cases around parsing datetime
.. image:: https://farm4.staticflickr.com/3702/33288285996_5b69d2b8f7_k_d.jpg
Art by `Sam Flores
<https://www.instagram.com/samagram12/>`_ (Photo by `Kenneth Reitz
<https://www.instagram.com/kennethreitz/>`_).
☤ Basic Usage of Maya
---------------------
@@ -73,6 +77,10 @@ Behold, datetimes for humans!
>>> m = maya.MayaDT.from_struct(time.gmtime())
>>> print(m)
Wed, 20 Sep 2017 17:24:32 GMT
>>> m = maya.MayaDT(time.time())
>>> print(m)
Wed, 20 Sep 2017 17:24:32 GMT
>>> rand_day.day
7
+1 -1
View File
@@ -1 +1 @@
__version__ = '0.3.4'
__version__ = '0.5.0'
+61 -14
View File
@@ -14,6 +14,7 @@ import pendulum
import snaptime
from tzlocal import get_localzone
from dateutil.relativedelta import relativedelta
from dateparser.languages.loader import default_loader
from .compat import cmp, comparable
@@ -152,7 +153,7 @@ class MayaDT(object):
def subtract_date(self, **kwargs):
"""Returns a timedelta object with the duration between the dates"""
return timedelta(self.epoch - kwargs['dt'].epoch)
return timedelta(seconds=self.epoch - kwargs['dt'].epoch)
def snap(self, instruction):
"""
@@ -257,6 +258,14 @@ class MayaDT(object):
dt = dt.replace(tzinfo=self._tz)
return dt
def local_datetime(self):
"""Returns a local timezone-aware datetime object
It's the same as:
mayaDt.datetime(to_timezone=mayaDt.local_timezone)
"""
return self.datetime(to_timezone=self.local_timezone, naive=False)
def iso8601(self):
"""Returns an ISO 8601 representation of the MayaDT."""
# Get a timezone-naive datetime.
@@ -269,7 +278,7 @@ class MayaDT(object):
def rfc3339(self):
"""Returns an RFC 3339 representation of the MayaDT."""
return self.datetime().strftime("%Y-%m-%dT%H:%M:%S.%f")[:-4] + "Z"
return self.datetime().strftime("%Y-%m-%dT%H:%M:%S.%f")[:-5] + "Z"
# Properties
# ----------
@@ -323,15 +332,39 @@ class MayaDT(object):
# Human Slang Extras
# ------------------
def slang_date(self):
""""Returns human slang representation of date."""
dt = self.datetime(naive=True, to_timezone=self.local_timezone)
return humanize.naturaldate(dt)
def slang_date(self, locale="en"):
""""Returns human slang representation of date.
def slang_time(self):
""""Returns human slang representation of time."""
dt = self.datetime(naive=True, to_timezone=self.local_timezone)
return humanize.naturaltime(dt)
Keyword Arguments:
locale -- locale to translate to, e.g. 'fr' for french.
(default: 'en' - English)
"""
dt = pendulum.instance(self.datetime())
try:
return _translate(dt, locale)
except KeyError:
pass
dt.set_formatter("alternative")
delta = humanize.time.abs_timedelta(
timedelta(seconds=(self.epoch - now().epoch)))
format_string = "DD MMM"
if delta.days >= 365:
format_string += " YYYY"
return dt.format(format_string, locale=locale).title()
def slang_time(self, locale="en"):
""""Returns human slang representation of time.
Keyword Arguments:
locale -- locale to translate to, e.g. 'fr' for french.
(default: 'en' - English)
"""
dt = self.datetime()
return pendulum.instance(dt).diff_for_humans(locale=locale)
def utc_offset(time_struct=None):
@@ -675,7 +708,7 @@ def now():
return MayaDT(epoch=epoch)
def when(string, timezone='UTC', prefer_past=False):
def when(string, timezone='UTC', prefer_dates_from='current_period'):
""""Returns a MayaDT instance for the human moment specified.
Powered by dateparser. Useful for scraping websites.
@@ -686,16 +719,20 @@ def when(string, timezone='UTC', prefer_past=False):
Keyword Arguments:
string -- string to be parsed
timezone -- timezone referenced from (default: 'UTC')
prefer_past -- prefer parsing ambiguous date as in the past
prefer_dates_from -- what dates are prefered when `string` is ambigous.
options are 'past', 'future', and 'current_period'
(default: 'current_period'). see: [1]
Reference:
[1] dateparser.readthedocs.io/en/latest/usage.html#handling-incomplete-dates
"""
settings = {
'TIMEZONE': timezone,
'RETURN_AS_TIMEZONE_AWARE': True,
'TO_TIMEZONE': 'UTC',
'PREFER_DATES_FROM': prefer_dates_from,
}
if prefer_past:
settings['PREFER_DATES_FROM'] = 'past'
dt = dateparser.parse(string, settings=settings)
if dt is None:
raise ValueError('invalid datetime input specified.')
@@ -747,6 +784,16 @@ def _seconds_or_timedelta(duration):
return dt_timedelta
def _translate(dt, target_locale):
en = default_loader.get_locale("en")
target = default_loader.get_locale(target_locale)
naturaldate = humanize.naturaldate(dt)
base = en.translate(naturaldate, settings=dateparser.conf.settings)
return target.info["relative-type"][base][-1]
def intervals(start, end, interval):
"""
Yields MayaDT objects between the start and end MayaDTs given,
+1 -1
View File
@@ -25,7 +25,7 @@ required = [
'pytz',
'dateparser>=0.7.0',
'tzlocal',
'pendulum>=1.0',
'pendulum>=1.0, <=1.5.1',
'snaptime'
]
+84 -14
View File
@@ -1,5 +1,6 @@
import copy
import time
import calendar
from datetime import timedelta, datetime as Datetime
import pytz
@@ -157,9 +158,19 @@ def test_slang_date():
assert d.slang_date() == 'tomorrow'
def test_slang_date_locale():
d = maya.when('tomorrow')
assert d.slang_date(locale='fr') == 'demain'
def test_slang_time():
d = maya.when('1 hour ago')
assert d.slang_time() == 'an hour ago'
assert d.slang_time() == '1 hour ago'
def test_slang_time_locale():
d = maya.when('1 hour ago')
assert d.slang_time(locale='de') == 'vor 1 Stunde'
@pytest.mark.parametrize("string,kwds,expected", [
@@ -191,16 +202,46 @@ def test_parse(string, kwds, expected):
@pytest.mark.usefixtures("frozen_now")
def test_when_past():
next_month = str(maya.now().add(months=1).month)
this_year = maya.now().year
last_year = this_year - 1
future_date = maya.when(next_month)
past_date = maya.when(next_month, prefer_past=True)
assert future_date.year == this_year
if next_month == '1':
assert past_date.year == this_year
else:
assert past_date.year == last_year
two_days_away = maya.now().add(days=2)
past_date = maya.when(
two_days_away.slang_date(),
prefer_dates_from='past')
assert past_date < maya.now()
@pytest.mark.usefixtures("frozen_now")
def test_when_future():
two_days_away = maya.now().add(days=2)
future_date = maya.when(
two_days_away.slang_date(),
prefer_dates_from='future')
assert future_date > maya.now()
@pytest.mark.usefixtures("frozen_now")
def test_when_past_day_name():
two_days_away = maya.now().add(days=2)
past_date = maya.when(
calendar.day_name[two_days_away.weekday],
prefer_dates_from='past')
assert past_date < maya.now()
@pytest.mark.usefixtures("frozen_now")
def test_when_future_day_name():
two_days_away = maya.now().add(days=2)
future_date = maya.when(
calendar.day_name[two_days_away.weekday],
prefer_dates_from='future')
assert future_date > maya.now()
def test_datetime_to_timezone():
@@ -208,13 +249,20 @@ def test_datetime_to_timezone():
assert dt.tzinfo.zone == 'US/Eastern'
def test_rfc3339():
def test_rfc3339_epoch():
mdt = maya.when('2016-01-01')
out = mdt.rfc3339()
mdt2 = maya.MayaDT.from_rfc3339(out)
assert mdt.epoch == mdt2.epoch
def test_rfc3339_format():
rfc3339 = maya.MayaDT.rfc3339(maya.when('2016-01-01T12:03:03Z'))
# it's important that the string has got a "max 1-digit millis" fragment
# as per https://tools.ietf.org/html/rfc3339#section-5.6
assert rfc3339 == '2016-01-01T12:03:03.0Z'
@pytest.mark.usefixtures("frozen_now")
def test_comparison_operations():
now = maya.now()
@@ -289,8 +337,8 @@ def test_dunder_sub():
def test_mayaDT_sub():
now = maya.now()
then = now.add(days=1)
assert then - now == timedelta(24 * 60 * 60)
assert now - then == timedelta(-24 * 60 * 60)
assert then - now == timedelta(seconds=24 * 60 * 60)
assert now - then == timedelta(seconds=-24 * 60 * 60)
def test_core_local_timezone(monkeypatch):
@@ -311,6 +359,28 @@ def test_core_local_timezone(monkeypatch):
assert mdt.local_timezone == 'UTC'
def test_getting_datetime_for_local_timezone(monkeypatch):
@property
def mock_local_tz(self):
class StaticTzInfo(object):
zone = 'Europe/Zurich'
def __repr__(self):
return "<StaticTzInfo 'Europe/Zurich'>"
return StaticTzInfo()
monkeypatch.setattr(maya.MayaDT, '_local_tz', mock_local_tz)
d = maya.parse('1994-02-21T12:00:00+05:30')
dt = pytz.timezone('Europe/Zurich').localize(
Datetime(1994, 2, 21, 7, 30))
assert d.local_datetime() == dt
@pytest.mark.parametrize("when_str,snap_str,expected_when", [
('Mon, 21 Feb 1994 21:21:42 GMT', '@d',
'Mon, 21 Feb 1994 00:00:00 GMT'),