Compare commits

...

29 Commits

Author SHA1 Message Date
kennethreitz 9766619d00 Merge pull request #189 from thomasleveil/midnight_in_paris
WIP: Midnight in paris - is this a bug ?
2024-07-19 09:04:30 -04:00
kennethreitz bcc4885f99 Update README.rst 2024-04-02 10:58:07 -04:00
kennethreitz 564fc5a49e Update README.rst 2024-04-02 10:57:45 -04:00
kennethreitz 722eb258b0 Merge pull request #193 from Lenqth/fix-before-1970
Fallback on error in datetime() before year 1970
2024-04-02 10:43:56 -04:00
kennethreitz 66ec91e6ce Merge pull request #198 from timgates42/bugfix_typos
docs: Fix a few typos
2024-04-02 10:43:06 -04:00
Timo Furrer 46ab6ac552 Merge pull request #199 from JessicaTegner/ci
Improvement to workflow, test fixes and new basis
2022-10-17 15:12:36 +02:00
JessicaTegner cd4b4e7e8b tests now also run on prs 2022-10-09 13:39:04 +02:00
JessicaTegner cde6097142 Removed parallel job limitation 2022-10-09 13:30:58 +02:00
JessicaTegner d9cd563d1b Updated abs_timedelta to be correct for ci tests 2022-10-09 13:27:49 +02:00
JessicaTegner 87776b19ae Update docs config to be able to get a successful build in ci 2022-10-09 12:39:31 +02:00
JessicaTegner 6da33e920d fixed flake8 errors to be able to test successful runs of ci 2022-10-09 12:38:51 +02:00
JessicaTegner b0b5bb7ff6 THis is why we have spaces around item elements 2022-10-09 12:28:44 +02:00
JessicaTegner 2a69de0a47 Updated workflow with more modern versions of actions and python 2022-10-09 12:24:24 +02:00
Tim Gates b127699de3 docs: Fix a few typos
There are small typos in:
- src/maya/core.py

Fixes:
- Should read `preferred` rather than `prefered`.
- Should read `ambiguous` rather than `ambigous`.
2022-07-12 18:04:40 +10:00
Timo Furrer f3f95a92ee Update README.rst 2022-05-13 20:58:22 +02:00
Timo Furrer bf16792875 Looking for a new maintainer 2022-05-13 20:57:57 +02:00
Timo Furrer be42580883 Merge pull request #195 from santiagobasulto/master
Notebooks.ai is shutting down - Remove demo
2021-11-05 09:26:51 +01:00
Santiago Basulto 03540c48c1 Remove demo from README 2021-11-04 19:45:28 -03:00
Lenqth 2845e5dee0 Fallback on error in datetime() before year 1970 2021-04-19 15:31:37 +09:00
Thomas LEVEIL 882a6aead7 flake8 fixes 2020-08-22 00:17:58 +02:00
Thomas LEVEIL c0bf037d2e add tests for midnight in Paris 2020-08-22 00:17:58 +02:00
Timo Furrer b12a8dad11 Remove the stale bot for now 2020-05-20 09:19:47 +02:00
Timo Furrer 0a7061c125 Merge pull request #186 from cognifloyd/snap_tz
Add timezone aware snap modifiers
2020-05-20 09:18:35 +02:00
Jacob Floyd d0d3b0136e Add timezone aware snap modifiers
This allows for modifications in the given timezone. ie, snapping to the
beginning of the day with @d uses midnight in the given timezone instead
of in UTC. As usual, the maya object returned is back in UTC, only the
modifications happen in the requested timezone.
2020-03-12 18:16:10 -05:00
Timo Furrer ff2a417198 Merge pull request #181 from timgates42/bugfix/typo_quantized
Fix simple typo: quanitzed -> quantized
2019-12-09 12:52:01 +01:00
Tim Gates 669ef888e8 Fix simple typo: quanitzed -> quantized
Closes #180
2019-12-09 21:24:15 +11:00
Timo Furrer 11c0d683d7 Merge pull request #149 from wtty-fool/feature/maya-long-count
Maya Long Count
2019-11-05 08:56:55 +01:00
wtty-fool 8493dd7e84 Mayan Long Count tests 2019-09-01 14:04:19 +02:00
wtty-fool d900ed2d2c Added conversion to and from Mayan Long Count 2019-09-01 14:00:02 +02:00
7 changed files with 227 additions and 47 deletions
+10 -13
View File
@@ -1,6 +1,6 @@
name: Continuous Integration and Deployment
on: [push]
on: [push, pull_request]
jobs:
build:
@@ -8,15 +8,14 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
max-parallel: 4
matrix:
python-version: [2.7, 3.5, 3.6, 3.7]
os: [ubuntu-latest, macOS-latest]
python-version: ["3.6", "3.7", "3.8", "3.9", "3.10"]
os: [ubuntu-latest, macOS-latest, windows-latest]
steps:
- uses: actions/checkout@v1
- uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v1
uses: actions/setup-python@v4.2.0
with:
python-version: ${{ matrix.python-version }}
- name: Setup build and test environment
@@ -46,9 +45,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: actions/checkout@v3
- name: Set up Python 3.7
uses: actions/setup-python@v1
uses: actions/setup-python@v4.2.0
with:
python-version: 3.7
- name: Setup docs environment
@@ -62,20 +61,18 @@ jobs:
needs: [build, docs]
runs-on: ubuntu-latest
if: startsWith(github.event.ref, 'refs/tags') && github.ref == 'refs/heads/master'
steps:
- uses: actions/checkout@v1
- uses: actions/checkout@v3
- name: Set up Python 3.7
if: startsWith(github.event.ref, 'refs/tags')
uses: actions/setup-python@v1
uses: actions/setup-python@v4.2.0
with:
python-version: 3.7
- name: Build Package
if: startsWith(github.event.ref, 'refs/tags')
run: |
python -m pip install --upgrade pip setuptools wheel
python setup.py sdist bdist_wheel --universal
- name: Publish Package on PyPI
if: startsWith(github.event.ref, 'refs/tags')
uses: pypa/gh-action-pypi-publish@master
with:
user: __token__
-18
View File
@@ -1,18 +0,0 @@
name: "Close Stale Issues and Pull Requests"
on:
schedule:
- cron: "0 * * * *"
jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v1
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
days-before-stale: 60
days-before-close: 7
stale-issue-label: stale
stale-pr-label: state
stale-issue-message: 'This Issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 7 days'
stale-pr-message: 'This Pull Request is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 7 days'
+6 -11
View File
@@ -92,6 +92,11 @@ Behold, datetimes for humans!
>>> dt.snap('@d+3h').rfc2822()
'Mon, 21 Feb 1994 03:00:00 GMT'
# snap modifiers within a timezone
>>> dt = maya.when('Mon, 21 Feb 1994 21:21:42 GMT')
>>> dt.snap_tz('+3h@d', 'Australia/Perth').rfc2822()
'Mon, 21 Feb 1994 16:00:00 GMT'
☤ Advanced Usage of Maya
------------------------
@@ -126,7 +131,7 @@ From here, there are a number of methods available to you, which you can use to
☤ What about Delorean_, Arrow_, & Pendulum_?
-----------------------------------------
--------------------------------------------
All these projects complement each other, and are friends. Pendulum, for example, helps power Maya's parsing.
@@ -149,16 +154,6 @@ Installation is easy, with:
$ pip install maya
☤ Demo
------
Try ``maya`` interactively using this online demo:
.. image:: https://user-images.githubusercontent.com/1155573/49400125-16e73500-f722-11e8-9275-e1d7eb3bbf99.png
:target: https://notebooks.ai/demo/gh/kennethreitz/maya
:alt: Open Live Demo
How to Contribute
-----------------
+1 -1
View File
@@ -73,7 +73,7 @@ release = maya.__version__
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = None
language = "en"
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
+44 -4
View File
@@ -153,6 +153,17 @@ class MayaDT(object):
"""
return self.from_datetime(snaptime.snap(self.datetime(), instruction))
def snap_tz(self, instruction, in_timezone):
"""
Returns a new MayaDT object modified by the given instruction.
The modifications happen in the given timezone.
Powered by snaptime. See https://github.com/zartstrom/snaptime
for a complete documentation about the snaptime instructions.
"""
dt_tz = self.datetime(to_timezone=in_timezone)
return self.from_datetime(snaptime.snap_tz(dt_tz, instruction, dt_tz.tzinfo))
# Timezone Crap
# -------------
@property
@@ -212,6 +223,16 @@ class MayaDT(object):
"""Returns MayaDT instance from iso8601 string."""
return parse(iso8601_string)
@classmethod
def from_long_count(klass, long_count_string):
"""Returns MayaDT instance from Maya Long Count string."""
days_since_creation = -1856305
factors = (144000, 7200, 360, 20, 1)
for i, value in enumerate(long_count_string.split('.')):
days_since_creation += int(value) * factors[i]
days_since_creation *= 3600 * 24
return klass(epoch=days_since_creation)
@staticmethod
def from_rfc2822(rfc2822_string):
"""Returns MayaDT instance from rfc2822 string."""
@@ -236,7 +257,10 @@ class MayaDT(object):
if to_timezone:
dt = self.datetime().astimezone(pytz.timezone(to_timezone))
else:
dt = Datetime.utcfromtimestamp(self._epoch)
try:
dt = Datetime.utcfromtimestamp(self._epoch)
except: # Fallback for before year 1970 issue
dt = Datetime.utcfromtimestamp(0) + timedelta(microseconds=self._epoch*1000000)
dt.replace(tzinfo=self._tz)
# Strip the timezone info if requested to do so.
if naive:
@@ -269,6 +293,22 @@ class MayaDT(object):
"""Returns an RFC 3339 representation of the MayaDT."""
return self.datetime().strftime("%Y-%m-%dT%H:%M:%S.%f")[:-5] + "Z"
def long_count(self):
"""Returns a Mayan Long Count representation of the Maya DT."""
# Creation (0.0.0.0.0) occurred on -3114-08-11
# 1856305 is distance (in days) between Creation and UNIX epoch
days_since_creation = int(1856305 + self._epoch / (3600 * 24))
caps = (0, 20, 20, 18, 20)
lc_date = [0, 0, 0, 0, days_since_creation]
for i in range(4, 0, -1):
if lc_date[i] >= caps[i]:
lc_date[i - 1] += int(lc_date[i] / caps[i])
lc_date[i] %= caps[i]
elif lc_date[i] < 0:
lc_date[i - 1] += int(lc_date[i] / caps[i])
lc_date[i] = 0
return '.'.join(str(i) for i in lc_date)
# Properties
# ----------
@property
@@ -335,7 +375,7 @@ class MayaDT(object):
except KeyError:
pass
delta = humanize.time.abs_timedelta(
delta = humanize.time._abs_timedelta(
timedelta(seconds=(self.epoch - now().epoch))
)
@@ -576,7 +616,7 @@ class MayaInterval(object):
start += duration
def quantize(self, duration, snap_out=False, timezone="UTC"):
"""Returns a quanitzed interval."""
"""Returns a quantized interval."""
# Convert seconds to timedelta, if appropriate.
duration = _seconds_or_timedelta(duration)
timezone = pytz.timezone(timezone)
@@ -684,7 +724,7 @@ def when(string, timezone="UTC", prefer_dates_from="current_period"):
Keyword Arguments:
string -- string to be parsed
timezone -- timezone referenced from (default: 'UTC')
prefer_dates_from -- what dates are prefered when `string` is ambigous.
prefer_dates_from -- what dates are preferred when `string` is ambiguous.
options are 'past', 'future', and 'current_period'
(default: 'current_period'). see: [1]
+73
View File
@@ -1,3 +1,6 @@
import datetime
import pytz
from freezegun import freeze_time
import pytest
@@ -23,3 +26,73 @@ def frozen_now(request):
now_string, tz_offset = request.param
with freeze_time(now_string, tz_offset=tz_offset):
yield
@pytest.fixture(params=[
datetime.datetime(2020, 8, 10, 22, 2, 0, tzinfo=pytz.timezone('UTC')),
datetime.datetime(2020, 8, 10, 23, 2, 0, tzinfo=pytz.timezone('UTC')),
datetime.datetime(2020, 8, 11, 0, 2, 0, tzinfo=pytz.timezone('UTC')),
datetime.datetime(2020, 8, 11, 1, 2, 0, tzinfo=pytz.timezone('UTC')),
datetime.datetime(2020, 8, 11, 2, 2, 0, tzinfo=pytz.timezone('UTC')),
datetime.datetime(2020, 8, 11, 3, 2, 0, tzinfo=pytz.timezone('UTC')),
datetime.datetime(2020, 8, 11, 4, 2, 0, tzinfo=pytz.timezone('UTC')),
datetime.datetime(2020, 8, 11, 5, 2, 0, tzinfo=pytz.timezone('UTC')),
datetime.datetime(2020, 8, 11, 6, 2, 0, tzinfo=pytz.timezone('UTC')),
datetime.datetime(2020, 8, 11, 7, 2, 0, tzinfo=pytz.timezone('UTC')),
datetime.datetime(2020, 8, 11, 8, 2, 0, tzinfo=pytz.timezone('UTC')),
datetime.datetime(2020, 8, 11, 9, 2, 0, tzinfo=pytz.timezone('UTC')),
datetime.datetime(2020, 8, 11, 10, 2, 0, tzinfo=pytz.timezone('UTC')),
datetime.datetime(2020, 8, 11, 11, 2, 0, tzinfo=pytz.timezone('UTC')),
datetime.datetime(2020, 8, 11, 12, 2, 0, tzinfo=pytz.timezone('UTC')),
datetime.datetime(2020, 8, 11, 13, 2, 0, tzinfo=pytz.timezone('UTC')),
datetime.datetime(2020, 8, 11, 14, 2, 0, tzinfo=pytz.timezone('UTC')),
datetime.datetime(2020, 8, 11, 15, 2, 0, tzinfo=pytz.timezone('UTC')),
datetime.datetime(2020, 8, 11, 16, 2, 0, tzinfo=pytz.timezone('UTC')),
datetime.datetime(2020, 8, 11, 17, 2, 0, tzinfo=pytz.timezone('UTC')),
datetime.datetime(2020, 8, 11, 18, 2, 0, tzinfo=pytz.timezone('UTC')),
datetime.datetime(2020, 8, 11, 19, 2, 0, tzinfo=pytz.timezone('UTC')),
datetime.datetime(2020, 8, 11, 20, 2, 0, tzinfo=pytz.timezone('UTC')),
datetime.datetime(2020, 8, 11, 21, 2, 0, tzinfo=pytz.timezone('UTC')),
], ids=str)
def frozen_2020_08_11_in_paris(request):
"""
fixture setting datetime.now() to every hour of the 11th of august 2020 in Paris
(summer time, GMT+2)
"""
with freeze_time(request.param):
yield
@pytest.fixture(params=[
datetime.datetime(2020, 2, 10, 23, 2, 0, tzinfo=pytz.timezone('UTC')),
datetime.datetime(2020, 2, 11, 0, 2, 0, tzinfo=pytz.timezone('UTC')),
datetime.datetime(2020, 2, 11, 1, 2, 0, tzinfo=pytz.timezone('UTC')),
datetime.datetime(2020, 2, 11, 2, 2, 0, tzinfo=pytz.timezone('UTC')),
datetime.datetime(2020, 2, 11, 3, 2, 0, tzinfo=pytz.timezone('UTC')),
datetime.datetime(2020, 2, 11, 4, 2, 0, tzinfo=pytz.timezone('UTC')),
datetime.datetime(2020, 2, 11, 5, 2, 0, tzinfo=pytz.timezone('UTC')),
datetime.datetime(2020, 2, 11, 6, 2, 0, tzinfo=pytz.timezone('UTC')),
datetime.datetime(2020, 2, 11, 7, 2, 0, tzinfo=pytz.timezone('UTC')),
datetime.datetime(2020, 2, 11, 8, 2, 0, tzinfo=pytz.timezone('UTC')),
datetime.datetime(2020, 2, 11, 9, 2, 0, tzinfo=pytz.timezone('UTC')),
datetime.datetime(2020, 2, 11, 10, 2, 0, tzinfo=pytz.timezone('UTC')),
datetime.datetime(2020, 2, 11, 11, 2, 0, tzinfo=pytz.timezone('UTC')),
datetime.datetime(2020, 2, 11, 12, 2, 0, tzinfo=pytz.timezone('UTC')),
datetime.datetime(2020, 2, 11, 13, 2, 0, tzinfo=pytz.timezone('UTC')),
datetime.datetime(2020, 2, 11, 14, 2, 0, tzinfo=pytz.timezone('UTC')),
datetime.datetime(2020, 2, 11, 15, 2, 0, tzinfo=pytz.timezone('UTC')),
datetime.datetime(2020, 2, 11, 16, 2, 0, tzinfo=pytz.timezone('UTC')),
datetime.datetime(2020, 2, 11, 17, 2, 0, tzinfo=pytz.timezone('UTC')),
datetime.datetime(2020, 2, 11, 18, 2, 0, tzinfo=pytz.timezone('UTC')),
datetime.datetime(2020, 2, 11, 19, 2, 0, tzinfo=pytz.timezone('UTC')),
datetime.datetime(2020, 2, 11, 20, 2, 0, tzinfo=pytz.timezone('UTC')),
datetime.datetime(2020, 2, 11, 21, 2, 0, tzinfo=pytz.timezone('UTC')),
datetime.datetime(2020, 2, 11, 22, 2, 0, tzinfo=pytz.timezone('UTC')),
], ids=str)
def frozen_2020_02_11_in_paris(request):
"""
fixture setting datetime.now() to every hour of the 11th of february 2020 in Paris
(winter time, GMT+1)
"""
with freeze_time(request.param):
yield
+93
View File
@@ -30,6 +30,21 @@ def test_iso8601(string, expected):
assert r == d.iso8601()
@pytest.mark.parametrize(
"string,expected",
[
('January 1, 1970', "12.17.16.7.5"),
('December 21, 2012', "13.0.0.0.0"),
('March 4, 1900', "12.14.5.10.0"),
],
)
def test_long_count(string, expected):
r = maya.parse(string).long_count()
d = maya.MayaDT.from_long_count(r)
assert r == expected
assert r == d.long_count()
@pytest.mark.parametrize(
"string,expected",
[
@@ -71,6 +86,28 @@ def test_issue_104():
t = maya.MayaDT.from_struct(t)
assert str(t) == "Wed, 11 Oct 2017 21:12:11 GMT"
def test_before_1970():
d1 = maya.when("1899-17-11 08:09:10")
assert d1.year == 1899
assert d1.month == 11
assert d1.day == 17
assert d1.week == 46
assert d1.weekday == 5
assert d1.hour == 8
assert d1.minute == 9
assert d1.second == 10
assert d1.microsecond == 0
# Test properties for maya.parse()
d2 = maya.parse("February 29, 1904 13:12:34")
assert d2.year == 1904
assert d2.month == 2
assert d2.day == 29
assert d2.week == 9
assert d2.weekday == 1
assert d2.hour == 13
assert d2.minute == 12
assert d2.second == 34
assert d2.microsecond == 0
def test_human_when():
r1 = maya.when("yesterday")
@@ -78,6 +115,42 @@ def test_human_when():
assert (r2.day - r1.day) in (1, -30, -29, -28, -27)
@pytest.mark.usefixtures("frozen_2020_08_11_in_paris")
def test_human_when_today_with_timezone_summer_time():
d = maya.when("today", timezone='Europe/Paris')
assert str(d.datetime(to_timezone="Europe/Paris").date()) == '2020-08-11'
@pytest.mark.usefixtures("frozen_2020_02_11_in_paris")
def test_human_when_today_with_timezone_winter_time():
d = maya.when("today", timezone='Europe/Paris')
assert str(d.datetime(to_timezone="Europe/Paris").date()) == '2020-02-11'
@pytest.mark.usefixtures("frozen_2020_08_11_in_paris")
def test_human_when_yesterday_with_timezone_summer_time():
d = maya.when("yesterday", timezone='Europe/Paris')
assert str(d.datetime(to_timezone="Europe/Paris").date()) == '2020-08-10'
@pytest.mark.usefixtures("frozen_2020_02_11_in_paris")
def test_human_when_yesterday_with_timezone_winter_time():
d = maya.when("yesterday", timezone='Europe/Paris')
assert str(d.datetime(to_timezone="Europe/Paris").date()) == '2020-02-10'
@pytest.mark.usefixtures("frozen_2020_08_11_in_paris")
def test_human_when_midnight_with_timezone_summer_time():
d = maya.when("midnight", timezone='Europe/Paris')
assert str(d.datetime(to_timezone="Europe/Paris")) == '2020-08-11 00:00:00+02:00'
@pytest.mark.usefixtures("frozen_2020_02_11_in_paris")
def test_human_when_midnight_with_timezone_winter_time():
d = maya.when("midnight", timezone='Europe/Paris')
assert str(d.datetime(to_timezone="Europe/Paris")) == '2020-02-11 00:00:00+01:00'
def test_machine_parse():
r1 = maya.parse("August 14, 2015")
assert r1.day == 14
@@ -368,3 +441,23 @@ def test_snaptime(when_str, snap_str, expected_when):
dt = dt.snap(snap_str)
# then
assert dt == maya.when(expected_when)
@pytest.mark.parametrize(
"when_str,snap_str,timezone,expected_when",
[
(
"Mon, 21 Feb 1994 21:21:42 GMT",
"@d",
"Australia/Perth",
"Mon, 21 Feb 1994 16:00:00 GMT",
)
],
)
def test_snaptime_tz(when_str, snap_str, timezone, expected_when):
# given
dt = maya.when(when_str)
# when
dt = dt.snap_tz(snap_str, timezone)
# then
assert dt == maya.when(expected_when)