Skip to content

Commit

Permalink
v11.3.0
Browse files Browse the repository at this point in the history
  • Loading branch information
GitRon committed Sep 17, 2024
1 parent 371259e commit b87adf4
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 17 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:

- name: Run pre-commit hooks
run: pre-commit run --all-files --hook-stage push

validate_migrations:
name: Validate migrations
runs-on: ubuntu-22.04
Expand Down
4 changes: 4 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

**11.3.0** (2024-09-17)
* Added date util functions `get_current_year` and `check_date_is_weekend`
* Improved date utils docs

**11.2.4** (2024-09-11)
* Added GitHub action trigger for PRs

Expand Down
2 changes: 1 addition & 1 deletion ambient_toolbox/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
"""Python toolbox of Ambient Digital containing an abundance of useful tools and gadgets."""

__version__ = "11.2.4"
__version__ = "11.3.0"
17 changes: 17 additions & 0 deletions ambient_toolbox/utils/date.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import calendar
import datetime
from calendar import monthrange
from typing import Optional, Union
Expand Down Expand Up @@ -165,3 +166,19 @@ def get_first_and_last_of_month(date_object: Optional[datetime.date] = None) ->
last_of_month = first_of_next_month - datetime.timedelta(days=1)

return first_of_month, last_of_month


def get_current_year() -> int:
"""
Returns the current year.
Useful in model defaults where you want to put a callable.
"""
return tz_today().year


def check_date_is_weekend(compare_date: datetime.date, weekend_days=(calendar.SATURDAY, calendar.SUNDAY)) -> bool:
"""
Determines if a given "compare_date" is on a weekday, based on "weekend_days",
which default to European weekend days.
"""
return compare_date.weekday() in weekend_days
72 changes: 57 additions & 15 deletions docs/features/utils/date.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,15 @@
### DateHelper

The date helper class provides constants to use when querying for weekdays ("Monday", "Tuesday") with the django ORM.
The assignment from numbers to weekdays is not standarised throughout the different django packages. For example,
in the ``calendar`` extension, Monday equals `0`, in the djang ORM, a Monday is represented by `2`.
The assignment from numbers to weekdays is not standardised throughout the different django packages.

For example, in the ``calendar`` extension, Monday equals `0`, in the Django ORM, a Monday is represented by `2`.

To avoid using the integers directly, you can use the constants from this class as follows:

````python
from ambient_toolbox.utils.date import DateHelper

# Just get records where `my_date` is on a Sunday
MyModel.objects.filter(my_date__week_day=DateHelper.ORM_SUNDAY)

Expand All @@ -22,7 +25,8 @@ MyModel.objects.exclude(my_date__week_day__in[DateHelper.ORM_SATURDAY, DateHelpe
The function ``add_months(source_date)`` provides a simple way to add any number of months to a given date:

````python
from ambient_toolbox.utils import add_months
import datetime
from ambient_toolbox.utils.date import add_months

new_date = add_months(datetime.date(year=2020, month=9, day=19), 2)
# new_date = datetime.date(2020, 11, 19)
Expand All @@ -35,7 +39,8 @@ You can also use a negative number to subtract months.
The function ``add_days(source_date)`` provides a simple way to add any number of months to a given date:

````python
from ambient_toolbox.utils import add_days
import datetime
from ambient_toolbox.utils.date import add_days

new_date = add_days(datetime.date(year=2020, month=9, day=19), 2)
# new_date = datetime.date(2020, 9, 21)
Expand All @@ -48,7 +53,8 @@ You can also use a negative number to subtract days.
The function ``add_minutes(source_datetime)`` provides a simple way to add any number of months to a given date:

````python
from ambient_toolbox.utils import add_days
import datetime
from ambient_toolbox.utils.date import add_minutes

new_datetime = add_minutes(datetime.datetime(year=2020, month=9, day=19, hour=8), 60)
# new_datetime = add_minutes.date(2020, 9, 19, 9)
Expand All @@ -65,7 +71,8 @@ The function ``get_next_month()`` is a wrapper for ``add_months()`` and will ret
The function ``first_day_of_month(source_date)`` will return the first of month for any given date:

````python
from ambient_toolbox.utils import first_day_of_month
import datetime
from ambient_toolbox.utils.date import first_day_of_month

new_date = first_day_of_month(datetime.date(year=2020, month=9, day=19))
# new_date = datetime.date(2020, 9, 1)
Expand All @@ -76,7 +83,8 @@ new_date = first_day_of_month(datetime.date(year=2020, month=9, day=19))
The function ``get_formatted_date_str(source_date)`` will return the string representation in the German format ("d.m.Y"):

````python
from ambient_toolbox.utils import get_formatted_date_str
import datetime
from ambient_toolbox.utils.date import get_formatted_date_str

date_str = get_formatted_date_str(datetime.date(year=2020, month=9, day=19))
# date_str = "19.09.2020"
Expand All @@ -89,7 +97,7 @@ The function ``get_time_from_seconds(seconds)`` will create a string representat
in the format "HH:mm:ss":

````python
from ambient_toolbox.utils import get_formatted_date_str
from ambient_toolbox.utils.date import get_time_from_seconds

time_str = get_time_from_seconds(3661)
# time_str = "01:01:01"
Expand All @@ -109,7 +117,10 @@ without the timezone is used:
TIME_ZONE = 'Europe/Berlin'

# my_code.py
source_date = datetime.datetime(year=2020, month=6, day=26, hour=8, tzinfo=pytz.UTC)
import datetime
from ambient_toolbox.utils.date import datetime_format

source_date = datetime.datetime(year=2020, month=6, day=26, hour=8, tzinfo=datetime.UTC)
datetime_str = datetime_format(source_date, '%d.%m.%Y %H:%M') # will return '26.06.2020 10:00'
````

Expand All @@ -119,7 +130,7 @@ The function ``get_start_and_end_date_from_calendar_week(year, calendar_week)``
and Sunday of a given calendar week:

````python
from ambient_toolbox.utils import get_start_and_end_date_from_calendar_week
from ambient_toolbox.utils.date import get_start_and_end_date_from_calendar_week

monday, sunday = get_start_and_end_date_from_calendar_week(2020, 38)
# monday = datetime.date(2020, 09, 14); sunday = datetime.date(2020, 9, 20)
Expand All @@ -132,7 +143,7 @@ The function ``get_next_calendar_week(compare_date)`` will return the the calend

````python
import datetime
from ambient_toolbox.utils import get_next_calendar_week
from ambient_toolbox.utils.date import get_next_calendar_week

next_calendar_week = get_next_calendar_week(datetime.date(year=2020, month=9, day=19))
# next_calendar_week = 39
Expand All @@ -145,7 +156,7 @@ The function ``next_weekday(given_date, weekday)`` will return a date object of
````python
import calendar
import datetime
from ambient_toolbox.utils import next_weekday
from ambient_toolbox.utils.date import next_weekday

next_friday = next_weekday(datetime.date(year=2020, month=9, day=19), calendar.FRIDAY)
# next_friday = datetime.date(year=2020, month=9, day=25)
Expand All @@ -160,7 +171,7 @@ float. So from April 15th to May 1st it's 0.5 months. Attention: The `end_date`
````python
import calendar
import datetime
from ambient_toolbox.utils import date_month_delta
from ambient_toolbox.utils.date import date_month_delta

months = date_month_delta(datetime.date(year=2020, month=8, day=1), datetime.date(year=2020, month=10, day=1))
# months = 2.0
Expand All @@ -173,7 +184,7 @@ The month is either the current month (if no date_object is passed), or the mont
Dates passed need to be datetime.date objects (not datetime.datetime)!

````python
from ambient_toolbox.utils import get_first_and_last_of_month
from ambient_toolbox.utils.date import get_first_and_last_of_month

# Today is 04.04.2022
first_of_month, last_of_month = get_first_and_last_of_month()
Expand All @@ -195,7 +206,7 @@ You can optionally use the argument ``str_format``, then the current date will b
function will return a string. Please provide a ``strftime``-compatible value.

````python
from ambient_toolbox.utils import next_weekday
from ambient_toolbox.utils.date import tz_today

# Here we'll get an object
current_date = tz_today()
Expand All @@ -204,6 +215,37 @@ current_date = tz_today()
current_date = tz_today('%d.%m.%Y')
````

### Get current year

The function ``get_current_year()`` will return the current year as an integer.

This is especially useful in model defaults where you want to put a callable instead of a fixed value.

````python
from ambient_toolbox.utils.date import get_current_year

current_year = get_current_year()
````


### Check if a date is on a weekend

The function ``check_date_is_weekend()`` will return a boolean value determining if the given date is on a weekend.

You can customise the default weekend days via the parameter `weekend_days`.

````python
import calendar
import datetime
from ambient_toolbox.utils.date import check_date_is_weekend

# This will result in False
is_on_weekend = check_date_is_weekend(datetime.date(2024, 9, 19))

# Imagine you live in certain areas of Malaysia, you can configure the weekend days
is_on_weekend = check_date_is_weekend(datetime.date(2024, 9, 19), weekend_days=(calendar.FRIDAY, calendar.SUNDAY))
````

## Object ownership helper

The function ``log_whodid`` provides a simple way to ensure object ownership is set correctly. Imagine, you have a model
Expand Down
22 changes: 22 additions & 0 deletions tests/test_utils_date.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@
add_days,
add_minutes,
add_months,
check_date_is_weekend,
date_month_delta,
datetime_format,
first_day_of_month,
get_current_year,
get_first_and_last_of_month,
get_formatted_date_str,
get_next_calendar_week,
Expand Down Expand Up @@ -266,3 +268,23 @@ def test_get_first_and_last_of_month_with_date_objects_passed(self):

self.assertEqual(date_mapping[date_object]["first"], first_of_month)
self.assertEqual(date_mapping[date_object]["last"], last_of_month)

@freeze_time("2017-06-26")
def test_get_current_year_regular(self):
self.assertEqual(get_current_year(), 2017)

@freeze_time("2017-12-31 23:59")
def test_get_current_year_end_of_year(self):
self.assertEqual(get_current_year(), 2017)

@freeze_time("2017-01-01 00:00")
def test_get_current_year_new_year(self):
self.assertEqual(get_current_year(), 2017)

def test_check_date_is_weekend_positive(self):
compare_date = datetime.date(year=2024, month=9, day=19)
self.assertIs(check_date_is_weekend(compare_date), False)

def test_check_date_is_weekend_negative(self):
compare_date = datetime.date(year=2024, month=9, day=21)
self.assertIs(check_date_is_weekend(compare_date), True)

0 comments on commit b87adf4

Please sign in to comment.