Skip to content

Commit

Permalink
1.2.0.1 [release]
Browse files Browse the repository at this point in the history
  • Loading branch information
bboonstra committed Oct 23, 2024
1 parent 34778d3 commit aa1fbc8
Show file tree
Hide file tree
Showing 5 changed files with 303 additions and 65 deletions.
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,20 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.2.0.1] - 2024-10-22

### Added

- Added Unix timestamp support to between_dates() conditions
- Date conditions are now timezone-aware (UTC)
- Fixed some typing issues

### Docs

- Added technical per-object documentation pages
- Updated themes and visuals
- Added a changelog page that reflects CHANGELOG.md

## [1.2.0] - 2024-10-22

### Added
Expand Down
4 changes: 2 additions & 2 deletions docs/docs/technical/fields.html
Original file line number Diff line number Diff line change
Expand Up @@ -184,8 +184,8 @@ <h4 class="method-subheader" method-parameters="value: any">
<p class="method-description">
Creates a condition that checks if the field's date is
between the given dates. Valid dates are either datetime
objects or strings in the yyyy-mm-dd format. Unix
timestamp support is coming soon!
objects, strings in the yyyy-mm-dd format, or Unix
timestamps.
</p>
<!-- prettier-ignore -->
<div class="command python example-usage">
Expand Down
45 changes: 34 additions & 11 deletions effortless/search.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from abc import ABC, abstractmethod
from typing import Callable, Union, Tuple, List, Type
import re
from datetime import datetime
from datetime import datetime, timezone
from difflib import SequenceMatcher


Expand Down Expand Up @@ -85,7 +85,7 @@ def _create_field_validator(self):
elif isinstance(self.field, str):
return lambda entry: self._field_exists(entry, self.field)
elif isinstance(self.field, (tuple, list)):
return lambda entry: all(self._field_exists(entry, f) for f in self.field) # type: ignore
return lambda entry: all(self._field_exists(entry, f) for f in self.field) # type: ignore
return lambda entry: False

def __and__(self, other):
Expand Down Expand Up @@ -275,28 +275,39 @@ def between_dates(self, start_date, end_date):
Create a condition that checks if the field's date is between the given dates.
Args:
start_date (datetime): The start date of the range.
end_date (datetime): The end date of the range.
start_date (Union[datetime, str, int, float]): The start date of the range.
end_date (Union[datetime, str, int, float]): The end date of the range.
Returns:
Query: This query object with the new condition.
Raises:
TypeError: If start_date or end_date is not a datetime object.
ValueError: If start_date is after end_date.
TypeError: If start_date or end_date is not a datetime, string, int, or float.
ValueError: If start_date is after end_date, if the date string format is invalid,
or if the Unix timestamp is invalid.
"""

def to_datetime(date):
if isinstance(date, str):
try:
return datetime.fromisoformat(date)
dt = datetime.fromisoformat(date)
return dt.replace(tzinfo=timezone.utc) if dt.tzinfo is None else dt
except ValueError:
raise ValueError(f"Invalid date format: {date}")
elif isinstance(date, datetime):
return date
return (
date.replace(tzinfo=timezone.utc) if date.tzinfo is None else date
)
elif isinstance(date, (int, float)):
if date < 0:
raise ValueError(f"Invalid Unix timestamp: {date}")
try:
return datetime.fromtimestamp(date, tz=timezone.utc)
except (ValueError, OSError, OverflowError):
raise ValueError(f"Invalid Unix timestamp: {date}")
else:
raise TypeError(
f"Date must be a string or datetime object, not {type(date)}"
f"Date must be a string, datetime, int, or float object, not {type(date)}"
)

start_date = to_datetime(start_date)
Expand All @@ -309,9 +320,22 @@ def condition(entry):
if isinstance(field_value, str):
try:
field_value = datetime.fromisoformat(field_value)
field_value = (
field_value.replace(tzinfo=timezone.utc)
if field_value.tzinfo is None
else field_value
)
except ValueError:
return False
if not isinstance(field_value, datetime):
elif isinstance(field_value, (int, float)):
field_value = datetime.fromtimestamp(field_value, tz=timezone.utc)
elif isinstance(field_value, datetime):
field_value = (
field_value.replace(tzinfo=timezone.utc)
if field_value.tzinfo is None
else field_value
)
else:
return False
return start_date <= field_value <= end_date

Expand Down Expand Up @@ -530,4 +554,3 @@ class FieldNotFoundError(Exception):
"""

pass

6 changes: 3 additions & 3 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@

setup(
name="Effortless",
version="1.2.0",
version="1.2.0.1",
packages=find_packages(),
description="Databases should be Effortless.",
long_description=open("README.md").read(),
long_description_content_type="text/markdown",
url="https://github.com/bboonstra/Effortless",
url="https://bboonstra.github.io/Effortless/",
author="Ben Boonstra",
license="MIT",
classifiers=[
Expand All @@ -30,7 +30,7 @@
keywords="database, effortless, simple storage, beginner, easy, db",
project_urls={
"Bug Tracker": "https://github.com/bboonstra/Effortless/issues",
"Documentation": "https://github.com/bboonstra/Effortless",
"Documentation": "https://bboonstra.github.io/Effortless/",
"Source Code": "https://github.com/bboonstra/Effortless",
},
include_package_data=True,
Expand Down
Loading

0 comments on commit aa1fbc8

Please sign in to comment.