Skip to content

Commit

Permalink
Add comments and improve documentation for Morrow library
Browse files Browse the repository at this point in the history
  • Loading branch information
Prodesire committed Oct 1, 2024
1 parent 4ac47cd commit 204ed3f
Show file tree
Hide file tree
Showing 6 changed files with 154 additions and 45 deletions.
6 changes: 6 additions & 0 deletions morrow/_py.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,16 @@ from python import Python, PythonObject


fn py_dt_datetime() raises -> PythonObject:
"""
Import and return the datetime class from Python's datetime module.
"""
var _datetime = Python.import_module("datetime")
return _datetime.datetime


fn py_time() raises -> PythonObject:
"""
Import and return the time module from Python.
"""
var _time = Python.import_module("time")
return _time
62 changes: 34 additions & 28 deletions morrow/formatter.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -8,32 +8,36 @@ from .constants import (
)
from .timezone import UTC_TZ

# Global formatter instance
alias formatter = _Formatter()


struct _Formatter:
# Vector to store the maximum number of repetitions for each formatting character
var _sub_chrs: InlinedFixedVector[Int, 128]

fn __init__(inout self):
self._sub_chrs = InlinedFixedVector[Int, 128](0)
for i in range(128):
self._sub_chrs[i] = 0
self._sub_chrs[_Y] = 4
self._sub_chrs[_M] = 4
self._sub_chrs[_D] = 2
self._sub_chrs[_d] = 4
self._sub_chrs[_H] = 2
self._sub_chrs[_h] = 2
self._sub_chrs[_m] = 2
self._sub_chrs[_s] = 2
self._sub_chrs[_S] = 6
self._sub_chrs[_Z] = 3
self._sub_chrs[_A] = 1
self._sub_chrs[_a] = 1
# Set the maximum number of repetitions for each formatting character
self._sub_chrs[_Y] = 4 # Year
self._sub_chrs[_M] = 4 # Month
self._sub_chrs[_D] = 2 # Day
self._sub_chrs[_d] = 4 # Day of week
self._sub_chrs[_H] = 2 # Hour (24-hour)
self._sub_chrs[_h] = 2 # Hour (12-hour)
self._sub_chrs[_m] = 2 # Minute
self._sub_chrs[_s] = 2 # Second
self._sub_chrs[_S] = 6 # Microsecond
self._sub_chrs[_Z] = 3 # Timezone
self._sub_chrs[_A] = 1 # AM/PM
self._sub_chrs[_a] = 1 # am/pm

fn format(self, m: Morrow, fmt: String) raises -> String:
"""
"YYYY[abc]MM" -> repalce("YYYY") + "abc" + replace("MM")
Format the Morrow object according to the given format string.
Handles brackets for literal text: "YYYY[abc]MM" -> replace("YYYY") + "abc" + replace("MM")
"""
if len(fmt) == 0:
return ""
Expand Down Expand Up @@ -64,7 +68,7 @@ struct _Formatter:

fn replace(self, m: Morrow, s: String) raises -> String:
"""
split token and replace
Replace formatting tokens in the string with their corresponding values
"""
if len(s) == 0:
return ""
Expand Down Expand Up @@ -95,6 +99,7 @@ struct _Formatter:
fn replace_token(
self, m: Morrow, token: Int, token_count: Int
) raises -> String:
# Replace individual formatting tokens based on their type and count
if token == _Y:
if token_count == 1:
return "Y"
Expand Down Expand Up @@ -175,17 +180,18 @@ struct _Formatter:
return ""


alias _Y = ord("Y")
alias _M = ord("M")
alias _D = ord("D")
alias _d = ord("d")
alias _H = ord("H")
alias _h = ord("h")
alias _m = ord("m")
alias _s = ord("s")
alias _S = ord("S")
alias _X = ord("X")
alias _x = ord("x")
alias _Z = ord("Z")
alias _A = ord("A")
alias _a = ord("a")
# Define constants for formatting characters
alias _Y = ord("Y") # Year
alias _M = ord("M") # Month
alias _D = ord("D") # Day
alias _d = ord("d") # Day of week
alias _H = ord("H") # Hour (24-hour)
alias _h = ord("h") # Hour (12-hour)
alias _m = ord("m") # Minute
alias _s = ord("s") # Second
alias _S = ord("S") # Microsecond
alias _X = ord("X") # Time
alias _x = ord("x") # Date
alias _Z = ord("Z") # Timezone
alias _A = ord("A") # AM/PM
alias _a = ord("a") # am/pm
28 changes: 18 additions & 10 deletions morrow/morrow.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,17 @@ struct Morrow(StringableRaising):

@staticmethod
fn now() -> Self:
"""
Return a Morrow object representing the current local date and time.
"""
var t = c_gettimeofday()
return Self._fromtimestamp(t, False)

@staticmethod
fn utcnow() -> Self:
"""
Return a Morrow object representing the current UTC date and time.
"""
var t = c_gettimeofday()
return Self._fromtimestamp(t, True)

Expand Down Expand Up @@ -131,7 +137,8 @@ struct Morrow(StringableRaising):
return Self.strptime(date_str, fmt, tzinfo)

fn format(self, fmt: String = "YYYY-MM-DD HH:mm:ss ZZ") raises -> String:
"""Returns a string representation of the `Morrow`
"""
Returns a string representation of the `Morrow`
formatted according to the provided format string.
:param fmt: the format string.
Expand All @@ -153,7 +160,8 @@ struct Morrow(StringableRaising):
fn isoformat(
self, sep: String = "T", timespec: StringLiteral = "auto"
) raises -> String:
"""Return the time formatted according to ISO.
"""
Return the time formatted according to ISO.
The full format looks like 'YYYY-MM-DD HH:MM:SS.mmmmmm'.
Expand Down Expand Up @@ -219,19 +227,17 @@ struct Morrow(StringableRaising):
return sep.join(date_str, time_str) + self.tz.format()

fn toordinal(self) raises -> Int:
"""Return proleptic Gregorian ordinal for the year, month and day.
January 1 of year 1 is day 1. Only the year, month and day values
contribute to the result.
"""
Return the proleptic Gregorian ordinal of the date, where January 1 of year 1 has ordinal 1.
"""
return _ymd2ord(self.year, self.month, self.day)

@staticmethod
fn fromordinal(ordinal: Int) raises -> Self:
"""Construct a Morrow from a proleptic Gregorian ordinal.
"""
Construct a Morrow object from a proleptic Gregorian ordinal.
January 1 of year 1 is day 1. Only the year, month and day are
non-zero in the result.
January 1 of year 1 is day 1. Only the year, month and day are non-zero in the result.
"""
# n is a 1-based index, starting at 1-Jan-1. The pattern of leap years
# repeats exactly every 400 years. The basic strategy is to find the
Expand Down Expand Up @@ -302,7 +308,9 @@ struct Morrow(StringableRaising):
return Self(year, month, n + 1)

fn isoweekday(self) raises -> Int:
# "Return day of the week, where Monday == 1 ... Sunday == 7."
"""
Return the day of the week as an integer, where Monday is 1 and Sunday is 7.
"""
# 1-Jan-0001 is a Monday
return self.toordinal() % 7 or 7

Expand Down
65 changes: 64 additions & 1 deletion morrow/timedelta.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ alias SECONDS_OF_DAY = 24 * 3600


struct TimeDelta(Stringable, Formattable):
"""
Represents a duration of time.
"""

var days: Int
var seconds: Int
var microseconds: Int
Expand All @@ -16,6 +20,9 @@ struct TimeDelta(Stringable, Formattable):
hours: Int = 0,
weeks: Int = 0,
):
"""
Initialize a TimeDelta object.
"""
self.days = 0
self.seconds = 0
self.microseconds = 0
Expand Down Expand Up @@ -50,6 +57,9 @@ struct TimeDelta(Stringable, Formattable):
self.days += days_

fn __copyinit__(inout self, other: Self):
"""
Copy constructor for TimeDelta.
"""
self.days = other.days
self.seconds = other.seconds
self.microseconds = other.microseconds
Expand All @@ -73,69 +83,107 @@ struct TimeDelta(Stringable, Formattable):
writer.write(str(self.microseconds).rjust(6, "0"))

fn total_seconds(self) -> Float64:
"""Total seconds in the duration."""
"""
Calculate the total number of seconds in the TimeDelta.
"""
return (
(self.days * 86400 + self.seconds) * 10**6 + self.microseconds
) / 10**6

@always_inline
fn __add__(self, other: Self) -> Self:
"""
Add two TimeDelta objects.
"""
return Self(
self.days + other.days,
self.seconds + other.seconds,
self.microseconds + other.microseconds,
)

fn __radd__(self, other: Self) -> Self:
"""
Reverse add operation for TimeDelta.
"""
return self.__add__(other)

fn __sub__(self, other: Self) -> Self:
"""
Subtract one TimeDelta from another.
"""
return Self(
self.days - other.days,
self.seconds - other.seconds,
self.microseconds - other.microseconds,
)

fn __rsub__(self, other: Self) -> Self:
"""
Reverse subtract operation for TimeDelta.
"""
return Self(
other.days - self.days,
other.seconds - self.seconds,
other.microseconds - self.microseconds,
)

fn __neg__(self) -> Self:
"""
Negate the TimeDelta.
"""
return Self(-self.days, -self.seconds, -self.microseconds)

fn __pos__(self) -> Self:
"""
Return a positive TimeDelta (self).
"""
return self

def __abs__(self) -> Self:
"""
Return the absolute value of the TimeDelta.
"""
if self.days < 0:
return -self
else:
return self

@always_inline
fn __mul__(self, other: Int) -> Self:
"""
Multiply the TimeDelta by an integer.
"""
return Self(
self.days * other,
self.seconds * other,
self.microseconds * other,
)

fn __rmul__(self, other: Int) -> Self:
"""
Reverse multiply operation for TimeDelta.
"""
return self.__mul__(other)

fn _to_microseconds(self) -> Int:
"""
Convert the TimeDelta to microseconds.
"""
return (
self.days * SECONDS_OF_DAY + self.seconds
) * 1000000 + self.microseconds

fn __mod__(self, other: Self) -> Self:
"""
Calculate the remainder of dividing this TimeDelta by another.
"""
var r = self._to_microseconds() % other._to_microseconds()
return Self(0, 0, r)

fn __eq__(self, other: Self) -> Bool:
"""
Check if two TimeDelta objects are equal.
"""
return (
self.days == other.days
and self.seconds == other.seconds
Expand All @@ -144,6 +192,9 @@ struct TimeDelta(Stringable, Formattable):

@always_inline
fn __le__(self, other: Self) -> Bool:
"""
Check if this TimeDelta is less than or equal to another.
"""
if self.days < other.days:
return True
elif self.days == other.days:
Expand All @@ -158,6 +209,9 @@ struct TimeDelta(Stringable, Formattable):

@always_inline
fn __lt__(self, other: Self) -> Bool:
"""
Check if this TimeDelta is less than another.
"""
if self.days < other.days:
return True
elif self.days == other.days:
Expand All @@ -171,12 +225,21 @@ struct TimeDelta(Stringable, Formattable):
return False

fn __ge__(self, other: Self) -> Bool:
"""
Check if this TimeDelta is greater than or equal to another.
"""
return not self.__lt__(other)

fn __gt__(self, other: Self) -> Bool:
"""
Check if this TimeDelta is greater than another.
"""
return not self.__le__(other)

fn __bool__(self) -> Bool:
"""
Check if the TimeDelta is non-zero.
"""
return self.days != 0 or self.seconds != 0 or self.microseconds != 0


Expand Down
Loading

0 comments on commit 204ed3f

Please sign in to comment.