Skip to content

Commit

Permalink
Merge pull request #31 from kuzmoyev/dev
Browse files Browse the repository at this point in the history
Add ruby style syntax
  • Loading branch information
kuzmoyev authored Sep 15, 2023
2 parents a5a9a61 + bd6cedd commit 3f85685
Show file tree
Hide file tree
Showing 8 changed files with 139 additions and 35 deletions.
47 changes: 29 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,22 +65,6 @@ BeautifulDate(2018, 3, 25)
BeautifulDate(2018, 3, 25)
```

Available formats (needed only if you create dates using `D@`):

```python3
class DMY(BaseDateFormat):
_format = 'day', 'month', 'year'

class MDY(BaseDateFormat):
_format = 'month', 'day', 'year'

class YMD(BaseDateFormat):
_format = 'year', 'month', 'day'

class YDM(BaseDateFormat):
_format = 'year', 'day', 'month'
```

You can also easily retrieve current date as a `BeautifulDate` object and current time using:

```python3
Expand All @@ -89,6 +73,12 @@ BeautifulDate(2020, 8, 24)

>>> D.now()
datetime.datetime(2020, 8, 24, 0, 59, 12, 451363)

>>> D.tomorrow()
BeautifulDate(2020, 8, 25)

>>> D.yesterday()
BeautifulDate(2020, 8, 23)
```

### Create Datetime
Expand Down Expand Up @@ -132,10 +122,31 @@ This library also provides simple interface for
[relativedelta](http://dateutil.readthedocs.io/en/stable/relativedelta.html) from
[dateutil](http://dateutil.readthedocs.io/en/stable/index.html)

#### Adding/Subtracting/Setting timedeltas:

Notice that singular time unit (year, month, ...) sets given value, plural (years, months,) adds it.

#### Shortcuts:

```python
>>> 5*days.from_today
BeautifulDate(2023, 9, 17)

>>> 1*hours.from_now
datetime.datetime(2023, 9, 12, 12, 53, 56)

>>> 3*days.since(15/Mar/2023)
BeautifulDate(2023, 3, 18)

>>> 5*days.until_today
BeautifulDate(2023, 9, 7)

>>> 1*hours.until_now
datetime.datetime(2023, 9, 12, 11, 13, 4)

>>> 3*days.until(15/Mar/2023)
BeautifulDate(2023, 3, 12)
```

#### Adding/Subtracting/Setting timedeltas:

```python3
>>> d = 26/Mar/2018
Expand Down
12 changes: 12 additions & 0 deletions beautiful_date/beautiful_date.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from datetime import date, datetime

from dateutil.relativedelta import relativedelta


class BeautifulDate(date):
"""Date object that can be extended to datetime by using Python indexing/slicing:
Expand Down Expand Up @@ -102,6 +104,16 @@ def today():
def now(tz=None):
return datetime.now(tz=tz)

@staticmethod
def tomorrow():
day = D.today() + relativedelta(days=1)
return BeautifulDate(year=day.year, month=day.month, day=day.day)

@staticmethod
def yesterday():
day = D.today() - relativedelta(days=1)
return BeautifulDate(year=day.year, month=day.month, day=day.day)


class DMY(BaseDateFormat):
_format = 'day', 'month', 'year'
Expand Down
79 changes: 66 additions & 13 deletions beautiful_date/beautiful_timedelta.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
from dateutil.relativedelta import relativedelta, weekdays
from datetime import date, datetime

from beautiful_date import BeautifulDate
from beautiful_date import BeautifulDate, D


class RelativeDelta(relativedelta):
class BeautifulRelativeDelta(relativedelta):
"""Same as relativedelta, but returns BeautifulDate in the result.
Examples:
Expand All @@ -23,21 +23,74 @@ def __add__(self, d):


class BeautifulTimedelta:
"""Creates timedelta with specified time unit using operator '*'
"""Creates timedelta with specified time unit using operator '*'."""

Examples:
>>> 3*years
RelativeDelta(years=+3)
>>> -5*weeks
RelativeDelta(days=-35)
"""

def __init__(self, name):
def __init__(self, name, start=None, is_until=False):
self.name = name
self.start = start
self.is_until = is_until

def __rmul__(self, n):
return RelativeDelta(**{self.name: n})
"""If start is set, returns BeautifulDate or datetime (depending on the start's type).
Examples:
>>> 5*days.from_today
BeautifulDate(2023, 9, 17)
>>> 1*hours.from_now
datetime.datetime(2023, 9, 12, 12, 53, 56)
>>> 5*days.until_today
BeautifulDate(2023, 9, 7)
>>> 1*hours.until_now
datetime.datetime(2023, 9, 12, 11, 13, 4)
Otherwise, returns BeautifulRelativeDelta.
Examples:
>>> 3*years
BeautifulRelativeDelta(years=+3)
>>> -5*weeks
BeautifulRelativeDelta(days=-35)
"""

if self.start is not None:
if self.is_until:
return self.start + BeautifulRelativeDelta(**{self.name: -n})
else:
return self.start + BeautifulRelativeDelta(**{self.name: n})
else:
return BeautifulRelativeDelta(**{self.name: n})

def from_(self, start):
return BeautifulTimedelta(self.name, start=start)

since = from_

@property
def from_now(self):
return self.from_(D.now())

@property
def from_today(self):
return self.from_(D.today())

def until(self, start):
return BeautifulTimedelta(self.name, start=start, is_until=True)

before = until

@property
def until_now(self):
return self.until(D.now())

ago = until_now

@property
def until_today(self):
return self.until(D.today())


_ = BeautifulTimedelta
Expand Down
4 changes: 3 additions & 1 deletion beautiful_tests/test_beautiful_date.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,11 @@ def test_datetime_create_by_prefix(self):
self.assertEqual((D @ 29 - 2 - 1988)[10:11:12],
datetime(day=29, month=2, year=1988, hour=10, minute=11, second=12))

def test_today_now(self):
def test_today_now_tomorrow_yesterday(self):
self.assertIsInstance(D.today(), BeautifulDate)
self.assertIsInstance(D.now(), datetime)
self.assertIsInstance(D.tomorrow(), BeautifulDate)
self.assertIsInstance(D.yesterday(), BeautifulDate)

def test_time_type_error(self):
with self.assertRaises(TypeError):
Expand Down
25 changes: 24 additions & 1 deletion beautiful_tests/test_beautiful_timedelta.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import unittest
from datetime import date, datetime

from freezegun import freeze_time

from beautiful_date import Feb, Mar, Oct, \
years, months, weeks, days, hours, minutes, seconds, microseconds, leapday, \
year, month, day, hour, minute, second, microsecond, yearday, nlyearday, \
MO, SA
MO, SA, D


class TestBeautifulTimedelta(unittest.TestCase):
Expand Down Expand Up @@ -101,3 +103,24 @@ def test_beautiful_weekdays(self):
self.assertEqual(d + MO(2), date(2018, 4, 9))
self.assertEqual(d - SA(2), date(2018, 3, 17))
self.assertEqual(d + SA(-2), date(2018, 3, 17))

def test_with_start(self):
initial_date = D.today()
with freeze_time(initial_date):
self.assertEqual(initial_date + 2 * days, 2 * days.from_today)
self.assertEqual(initial_date + 3 * days, 2 * days.from_(initial_date + 1 * days))
self.assertEqual(initial_date + 3 * days, 2 * days.since(initial_date + 1 * days))

self.assertEqual(initial_date - 2 * days, 2 * days.until_today)
self.assertEqual(initial_date - 3 * days, 2 * days.until(initial_date - 1 * days))
self.assertEqual(initial_date - 3 * days, 2 * days.before(initial_date - 1 * days))

initial_time = D.now()
with freeze_time(initial_time):
self.assertEqual(initial_time + 2 * hours, 2 * hours.from_now)
self.assertEqual(initial_time + 3 * hours, 2 * hours.from_(initial_time + 1 * hours))
self.assertEqual(initial_time + 3 * hours, 2 * hours.since(initial_time + 1 * hours))

self.assertEqual(initial_time - 2 * hours, 2 * hours.until_now)
self.assertEqual(initial_time - 3 * hours, 2 * hours.until(initial_time - 1 * hours))
self.assertEqual(initial_time - 3 * hours, 2 * hours.before(initial_time - 1 * hours))
4 changes: 2 additions & 2 deletions beautiful_tests/test_date_range.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,9 @@ def test_beautiful_drange_datetimes(self):

def test_repr(self):
self.assertEqual(repr(drange(27 / Mar / 1994, 5 / Apr / 1994)),
'drange(1994-03-27, 1994-04-05, RelativeDelta(days=+1))')
'drange(1994-03-27, 1994-04-05, BeautifulRelativeDelta(days=+1))')
self.assertEqual(repr(drange((27 / Mar / 1994)[10:25], (4 / Apr / 1994)[10:10], 12 * hours)),
'drange(1994-03-27 10:25:00, 1994-04-04 10:10:00, RelativeDelta(hours=+12))')
'drange(1994-03-27 10:25:00, 1994-04-04 10:10:00, BeautifulRelativeDelta(hours=+12))')

def test_zero_step_error(self):
with self.assertRaises(ValueError):
Expand Down
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ def run(self):
"pytest>=5.4",
"pytest-cov>=2.10",
"flake8>3.8.3",
"freezegun",
"tox"
]

Expand Down
2 changes: 2 additions & 0 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ omit =
deps =
pyfakefs
pytest
freezegun
commands =
pytest

Expand All @@ -38,6 +39,7 @@ deps =
pyfakefs
pytest
pytest-cov
freezegun
commands =
pytest --cov-report xml --cov=beautiful_date beautiful_tests

Expand Down

0 comments on commit 3f85685

Please sign in to comment.