Skip to content

Commit

Permalink
Add detailed docstrings for JalaliDate class methods and attributes
Browse files Browse the repository at this point in the history
  • Loading branch information
majiidd committed Jun 28, 2024
1 parent 7f7935d commit 453193a
Showing 1 changed file with 136 additions and 1 deletion.
137 changes: 136 additions & 1 deletion persiantools/jdatetime.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,16 @@

from persiantools import digits, utils

# The minimum year supported by the JalaliDate module
MINYEAR = 1

# The maximum year supported by the JalaliDate module
MAXYEAR = 9377

# The maximum ordinal value supported by the JalaliDate module
_MAXORDINAL = 3424878

# Full month names in English for the Jalali calendar
MONTH_NAMES_EN = [
None,
"Farvardin",
Expand All @@ -29,6 +35,8 @@
"Bahman",
"Esfand",
]

# Full month names in Persian for the Jalali calendar
MONTH_NAMES_FA = [
None,
"فروردین",
Expand All @@ -45,6 +53,7 @@
"اسفند",
]

# Abbreviated month names in English for the Jalali calendar
MONTH_NAMES_ABBR_EN = [
None,
"Far",
Expand All @@ -60,6 +69,8 @@
"Bah",
"Esf",
]

# Abbreviated month names in Persian for the Jalali calendar
MONTH_NAMES_ABBR_FA = [
None,
"فرو",
Expand All @@ -76,6 +87,7 @@
"اسف",
]

# Full weekday names in English for the Jalali calendar
WEEKDAY_NAMES_EN = [
"Shanbeh",
"Yekshanbeh",
Expand All @@ -85,11 +97,22 @@
"Panjshanbeh",
"Jomeh",
]

# Full weekday names in Persian for the Jalali calendar
WEEKDAY_NAMES_FA = ["شنبه", "یکشنبه", "دوشنبه", "سه‌شنبه", "چهارشنبه", "پنجشنبه", "جمعه"]

# Abbreviated weekday names in English for the Jalali calendar
WEEKDAY_NAMES_ABBR_EN = ["Sha", "Yek", "Dos", "Ses", "Cha", "Pan", "Jom"]

# Abbreviated weekday names in Persian for the Jalali calendar
WEEKDAY_NAMES_ABBR_FA = ["ش", "ی", "د", "س", "چ", "پ", "ج"]

# The number of days in each month of the Jalali calendar.
# Each list contains the following columns:
# 1. The number of days in the month for a non-leap year.
# 2. The number of days in the month for a leap year.
# 3. The cumulative number of days from the start of the year to the start of the month (in a non-leap year).
# The first entry is for indexing purposes and is not used in calculations.
_MONTH_COUNT = [
[-1, -1, -1], # for indexing purposes
[31, 31, 0], # farvardin
Expand Down Expand Up @@ -118,9 +141,39 @@ class JalaliDate:
locale (str): The locale for the Jalali date ('en' or 'fa').
"""

# Using __slots__ to declare a fixed set of attributes for the JalaliDate class.
# This helps to save memory by preventing the creation of a __dict__ for each instance.
# The attributes are:
# _year: The year of the Jalali date.
# _month: The month of the Jalali date.
# _day: The day of the Jalali date.
# _locale: The locale for the date representation (e.g., 'en' or 'fa').
# _hashcode: Cached hash code for the instance to speed up hash-based operations.
__slots__ = "_year", "_month", "_day", "_locale", "_hashcode"

def __init__(self, year, month=None, day=None, locale="en"):
"""
Initialize a JalaliDate object.
Args:
year (int, JalaliDate, datetime.date, bytes, or str): The year of the Jalali date. It can also be:
- An instance of JalaliDate.
- An instance of datetime.date.
- A 4-byte representation of the date.
- A string that starts with '['.
month (int, optional): The month of the Jalali date. Default is None.
day (int, optional): The day of the Jalali date. Default is None.
locale (str, optional): The locale for the date representation. It must be 'en' or 'fa'. Default is 'en'.
Raises:
ValueError: If the locale is not 'en' or 'fa'.
Notes:
- If `year` is an instance of JalaliDate and `month` is None, the date will be initialized with the values from the JalaliDate instance.
- If `year` is an instance of datetime.date, the date will be converted to Jalali date.
- If `year` is a 4-byte representation or a string starting with '[', the state will be set from these representations.
"""
if locale not in ["en", "fa"]:
raise ValueError("locale must be 'en' or 'fa'")

Expand Down Expand Up @@ -174,6 +227,21 @@ def locale(self, locale):

@classmethod
def _check_date_fields(cls, year, month, day, locale):
"""
Validate and normalize the date fields.
Args:
year (int): The year of the Jalali date.
month (int): The month of the Jalali date.
day (int): The day of the Jalali date.
locale (str): The locale for the date representation. It must be 'en' or 'fa'.
Returns:
tuple: A tuple containing validated and normalized year, month, day, and locale.
Raises:
ValueError: If the provided date fields are not valid.
"""
year = operator.index(year)
month = operator.index(month)
day = operator.index(day)
Expand All @@ -195,6 +263,21 @@ def _check_date_fields(cls, year, month, day, locale):

@classmethod
def check_date(cls, year, month, day):
"""
Check if the given Jalali date fields constitute a valid date.
Args:
year (int): The year of the Jalali date.
month (int): The month of the Jalali date (1 through 12).
day (int): The day of the Jalali date (1 through 31, depending on the month).
Returns:
bool: True if the provided date fields constitute a valid Jalali date, False otherwise.
Notes:
- This method checks whether the given year, month, and day form a valid Jalali date.
- It considers the specific rules for leap years in the Jalali calendar.
"""
try:
cls._check_date_fields(year, month, day, "en")
except (ValueError, TypeError):
Expand Down Expand Up @@ -419,10 +502,40 @@ def today(cls):
return cls(date.today())

def timetuple(self):
"Return local time tuple compatible with time.localtime()."
"""
Return the Jalali date as a time.struct_time object.
This method returns the Jalali date as a struct_time object, which is
similar to the output of the `time.localtime()` or `time.gmtime()` functions.
It contains year, month, day, hour, minute, second, weekday, Julian day, and DST flag.
Returns:
struct_time: A time.struct_time object representing the Jalali date.
Example:
>>> from persiantools.jdatetime import JalaliDate
>>> jdate = JalaliDate(1398, 3, 17)
>>> jdate.timetuple()
time.struct_time(tm_year=2019, tm_mon=6, tm_mday=7, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=4, tm_yday=158, tm_isdst=-1)
"""
return self.to_gregorian().timetuple()

def isoformat(self):
"""
Return the Jalali date as a string in ISO 8601 format.
This method returns the Jalali date as a string formatted according to the
ISO 8601 standard, which is `YYYY-MM-DD`.
Returns:
str: The Jalali date in ISO 8601 format.
Example:
>>> from persiantools.jdatetime import JalaliDate
>>> jdate = JalaliDate(1398, 3, 17)
>>> jdate.isoformat()
'1398-03-17'
"""
iso = "%04d-%02d-%02d" % (self._year, self._month, self._day)

if self._locale == "fa":
Expand Down Expand Up @@ -495,6 +608,28 @@ def __repr__(self):
resolution = timedelta(1)

def replace(self, year=None, month=None, day=None, locale=None):
"""
Return a new JalaliDate instance with one or more of the specified fields replaced.
This method allows for the replacement of the year, month, day, or locale
of an existing JalaliDate instance. If a field is not specified, the current
value of that field is retained.
Args:
year (int, optional): The new year value. Defaults to None.
month (int, optional): The new month value. Defaults to None.
day (int, optional): The new day value. Defaults to None.
locale (str, optional): The new locale value ('en' or 'fa'). Defaults to None.
Returns:
JalaliDate: A new JalaliDate instance with the specified fields replaced.
Example:
>>> jdate = JalaliDate(1400, 1, 1)
>>> new_jdate = jdate.replace(month=2)
>>> new_jdate
JalaliDate(1400, 2, 1)
"""
if year is None:
year = self._year

Expand Down

0 comments on commit 453193a

Please sign in to comment.