Reference

This chapter describes the specifics of the modules, classes, and methods provided by rhythm. It refrains from discussing how the parts might be used in a wider scope; the Usage document should be read for such information.

rhythm

Time is an illusion?

⌛ About

Warning

rhythm is a work in progress.

rhythm is a pure-Python datetime package based on the built-in Python int. By default, timestamps have nanosecond precision granting common applications more than enough detail about a point in time. For specialized purposes, the units handled by rhythm can be arbitrarily extended–the int subclasses represent a designated unit and a common Time Context, group of unit classes, provides the necessary linkage and transformations for conversion across classes.

Calendar Support:

  • Proleptic Gregorian

rhythm’s APIs are not compatible with the standard library’s datetime module. On purpose.

The surface functionality is provided in rhythm.lib:

import rhythm.lib

Current date and time as a rhythm.lib.Timestamp:

now = rhythm.lib.now() # UTC

Calendar Representation

A Date can be used to represent the span of the entire day:

date = rhythm.lib.Date.of(year=1982, month=4, day=17)
assert date.select('day', 'month') == 17

However, the above actually represents:

assert date.select('date') == (1982, 5, 18)

Usually, using the date keyword is best way to to work with literal dates:

assert rhythm.lib.Date.of(date=(1982,5,18)) == date

The calendrical representation only takes effect through certain interfaces:

ts = rhythm.lib.Timestamp.of(iso="2001-01-01T05:30:01")
print(repr(ts))
rhythm.lib.Timestamp.of(iso='2001-01-01T05:30:01.000000')

And from a datetime tuple:

ts2 = rhythm.lib.Timestamp.of(datetime = (2001, 1, 1, 5, 30, 1, 0))
assert ts == ts2

rhythm PiTs do not perform calendrical validation; rather, fields with excess values overflow onto larger units. This is similar to how MySQL handles overflow. For rhythm, this choice is deliberate and the user is expected to perform any desired validation:

pit = rhythm.lib.Date.of(date=(1982,5,0))

The assigned pit now points to the last day of the month preceding the fifth month in the year 1982. This kind of wrapping allows rhythm users to quickly perform some of the most difficult datetime math.

Datetime Math

rhythm can easily answer questions like, “What was third weekend of the fifth month of last year?”:

pit = rhythm.lib.now()
pit = pit.update('day', 0, 'month') # set to the first day to avoid overflow
pit = pit.rollback(year=1) # subtract one gregorian year
pit = pit.update('month', 5-1, 'year') # set to the fifth month
pit = pit.update('day', 6, 'week') # set to the weekend of the week
pit = pit.elapse(week = 2)

Things can get a little more interesting when asking, “What is the last weekend of the month?”. It’s not a problem:

# move the beginning of month (to avoid possible day overflow)
pit = rhythm.lib.now().update('day', 0, 'month')
# to the next month and then to the end of the previous
pit = pit.elapse(month = 1).update('day', -1, 'month') # move to the end of the month.
# 0 is the beginning of the week, so -1 is the end of the prior week.
pit = pit.update('day', -1, 'week')

On day overflow, the following illustrates the effect:

# working with a leap year
pit = rhythm.lib.Timestamp.of(iso='2012-01-31T18:55:33.946259')
pit.elapse(month=1)
rhythm.lib.Timestamp.of(iso='2012-03-02T18:55:33.946259')

Month arithmetic does not lose days in order to align the edge of a month. In order to keep overflow from causing invalid calculations, adjust to the beginning of the month.

Things can get even more interesting when asking, “What is the second to last Thursday of the month”. Questions like this require alignment in order to be answered:

pit = rhythm.lib.now()
pit = pit.update('day', 0, 'month') # let's say this month
# but we need the end of the month
pit = pit.elapse(month=1)
pit = pit.update('day', -1, 'month') # set to the first day
# And now something that will appear almost magical if
# you haven't used a datetime package with a similar feature.
pit = pit.update('day', 0, 'week', align=-4) # last thursday of month
pit = pit.rollback(week=1) # second to last

Essentially, alignment allows Thursdays to be seen as the first day of the week, warranting that the day field will stay the same or be subtracted when set to zero. This is why we set the day to the last day of the month, in case the Thursday is the last day of the month, and with proper alignment the first day of the week.

Clocks

rhythm.lib.now() provides quick and easy access to “demotic time”, UTC wall clock. However, rhythm provides clock based devices for processes with monotonic requirements for things like rate limiting, polling timeouts, and simple execution-time measures.

Measuring the execution time of a code block is easy with a rhythm stopwatch:

def work():
        pass

with rhythm.lib.clock.stopwatch() as snapshot:
        work()

print(snapshot())
print(snapshot())

Note

Considering the overhead involved with instantiating a rhythm.lib.Timestamp instance, measuring execution with the high-level clock interfaces may not be appropriate or may require some adjustments accounting for the overhead.

The current runtime of a stopwatch can be accessed within the block as well. However, once the block exits, the stopwatch will stop tracking elapsed time.

Deltas and meters provide a means to track the change in, monotonic, time:

for measure_since_last_iteration in rhythm.lib.clock.delta():
        pass

Meters are like deltas, but provide the total measurement:

for measure_since_first_iteration in rhythm.lib.clock.meter():
        pass

Time Zones

Time zone adjustments are supported by selecting Offset objects from a given point in time object:

pit = rhythm.lib.now()
offset = pit.select('tzoffset', 'America/Los_Angeles')
local_pit = pit.elapse(offset)
print(local_pit.select('iso'))

Fin

See the package documentation, for more details on using rhythm:

rhythm.lib

This is the primary module for using the datetime types and functions in the rhythm package.

Unit Knowledge

All of the following units are defined in the default Time Context. However, the emphasized units are the only units with designated classes.

Earth
  • second
  • minute
  • hour
  • day
  • week
  • annum (Julian Year)
Gregorian
  • month
  • year
  • decade
  • century
  • millennium
Metric Small
  • decisecond
  • centisecond
  • millisecond
  • microsecond
  • nanosecond
  • picosecond
  • femtosecond
  • attosecond
  • zeptosecond
  • yoctosecond
Metric Large
  • decasecond
  • hectosecond
  • kilosecond
  • megasecond
  • gigasecond
  • terasecond
  • petasecond
  • exasecond
  • zettasecond
  • yottasecond

The units in bold are the units with designated Python types. All other units are expressed in terms of those units unless the time context is explicitly extended.

rhythm.lib.Date

Point In Time with earth-day precision. rhythm.abstract.Point

alias of Point

rhythm.lib.Days

Scalar in earth-days. rhythm.abstract.Time

alias of Measure

rhythm.lib.GregorianMonth

Point In Time with Gregorian Month precision. rhythm.abstract.Point

alias of Point

class rhythm.lib.Measure

Bases: rhythm.libunit.Measure

Scalar with finest, default, representation type precision. rhythm.abstract.Time .. note:: Currently this is nanosecond precision, but rhythm reserves the right to increase the precision.

rhythm.lib.MeasureTypes = (<class 'rhythm.libunit.Context.measure_factory.<locals>.Measure'>, <class 'rhythm.libunit.Context.measure_factory.<locals>.Measure'>, <class 'rhythm.libunit.Context.measure_factory.<locals>.Measure'>, <class 'rhythm.libunit.Context.measure_factory.<locals>.Measure'>)

A tuple containing all of the default Scalar types.

rhythm.lib.Months

Scalar in Gregorian Months. rhythm.abstract.Time

alias of Measure

rhythm.lib.PointTypes = (<class 'rhythm.libunit.Context.point_factory.<locals>.Point'>, <class 'rhythm.libunit.Context.point_factory.<locals>.Point'>, <class 'rhythm.libunit.Context.point_factory.<locals>.Point'>, <class 'rhythm.libunit.Context.point_factory.<locals>.Point'>)

A tuple containing all of the default Point in Time types.

rhythm.lib.Timestamp

Point In Time with Measure’s precision. rhythm.abstract.Point

alias of Point

rhythm.lib.Week

Point In Time with seven earth-day precision. rhythm.abstract.Point

alias of Point

rhythm.lib.Weeks

Scalar in seven earth-days. rhythm.abstract.Time

alias of Measure

rhythm.lib.business_week(pit, five=rhythm.lib.Days.of(day=5), one=rhythm.lib.Days.of(day=1))[source]

Return an iterator to the business days in the week of the given pit.

rhythm.lib.now = <bound method Clock.demotic of <rhythm.libclock.Clock object at 0x10407efc8>>

Shortcut to rhythm.lib.clock.snapshot

rhythm.lib.open

Composition constructor for instantiating Time Objects from Container types. Example:

from rhythm import lib
from_iso = lib.open.iso(lib.Timestamp)
pit = from_iso("2002-01-01T3:45:00")
rhythm.lib.range(start, stop, step=None, Range=<class 'rhythm.libunit.Range'>)[source]

Construct an iterator producing Points between the given start and stop.

If step is provided, it will determine the difference to apply to the starting position for each iteration. If it is not provided, the step defaults to the rhythm.abstract.Point.magnitude of the start.

Example:

pit = rhythm.lib.now()
begin = pit.update('day', 1, 'week')
this_business_week = rhythm.lib.range(week_start, week_end, lib.Days(1))
rhythm.lib.select

Composition constructor for selecting parts from Time Objects. For instance, select.day.week().

rhythm.lib.unix(unix_timestamp)[source]

Create a rhythm.lib.Timestamp instance from seconds since the unix epoch.

Example:

import rhythm.lib
x = rhythm.lib.unix(0)
repr(x)
# rhythm.lib.Timestamp.of(iso='1970-01-01T00:00:00.000000')
rhythm.lib.update

Composition constructor for updating Time Objects. For instance, update.day.week(0).

rhythm.lib.zone(name=None, construct=<function unix at 0x10409b8c0>, zone_open=<function Zone.open at 0x104006830>)[source]

Return a Zone object for localizing UTC timestamps and normalizing local timestamps.

rhythm.libclock

System clock management and query interface.

class rhythm.libclock.Clock(unit, lib, clockwork=<module 'rhythm.system' from '/src/io/jwp/py-rhythm/rhythm/system.py'>)[source]

Bases: builtins.object

Operating System’s rhythm.abstract.Clock implementation.

rhythm.libflow

libflow provides tools for tracking arbitrary units over a period of time.

The classes and function herein are requisites for time based rate limiting.

class rhythm.libflow.Radar(Chronometer=<class 'rhythm.posix.Chronometer'>, Dictionary=<class 'weakref.WeakKeyDictionary'>, Queue=<class 'collections.deque'>)[source]

Bases: builtins.object

Radars track the rate of arbitrary flows across units of time. By default, objects are tracked using a weakref.WeakKeyDictionary. This allows for casual tracking to take place such that explicit disposal is not necessary. However, it is possible to use a regular dictionary by providing a type via the Dictionary keyword argument.

Radars are not thread safe with respect to particular subjects.

all(window, Measure=<class 'rhythm.libunit.Context.measure_factory.<locals>.Measure'>)[source]

overall(window)

Scan the entire set of tracked objects updating their rate according to a zero-units in order to get an up-to-date snapshot of the rate of all tracked objects for the given window.

Warning

Given the processing time necessary to calculate the totals for all tracked flows, overall may not ever be able to give an accurate answer.

collapse(subject, window = 0)[source]
Parameters:
  • subject (object) – The object whose flow is to be collapsed.
  • window (int) – The window of the flow to maintain.
Returns:

The number of records collapsed.

Return type:

int

Collapse calculates the tracked units and time of a given flow and replaces the set of records with a single record containing the totals. If a window is given, the consistency of the specified time frame will remain intact, but everything that comes before it will be aggregated into a single record.

This offers an alternative to truncate given cases where overall data is still needed.

forget(subject)[source]
Parameters:subject (object) – The tracked object to be removed.
Returns:The value of the forgotten key, subject.
Return type:object

Forget all tracking information about the given object, subject.

This removes the subject from the dictionary of tracked objects.

Note

By default, the dictionary is a WeakKeyDictionary. Using forget is not necessary unless an override for the dictionary type was given.

rate(subject, window=None)[source]
Parameters:
  • subject (object) – The tracked object.
  • window (int | NoneType) – The limit of view of the rate.

Construct a tuple of the (total units, total time) for the given subject and within the specified window.

If no window is provided, the overall units over time will be returned.

Uses the sums() method to construct the product.

static split(seq, pit)[source]
Parameters:
  • seq (int) – A sequence of (units, time) pairs.
  • pit – A point in time relative to the beginning of the sequence.
Returns:

A pair of sequences split at the given pit.

Return type:

list

Split the given sequence at the relative point in time within the given sequence, seq.

static sums(seq)[source]

Given a sequence of (time, units) pairs, return the sums of the columns.

track(subject, units)[source]

Given an object, track the units.

truncate(subject, window)[source]
Parameters:window (rhythm.lib.Measure) – The amount of time in the past to retain.
Returns:The number of records removed.
Return type:int

For the given object, truncate the tracked data according to the specified window of time units. All record data prior to the window will be discarded.

zero(subject)[source]
Parameters:subject (object) – The object whose flow-time is to be zeroed.
Returns:The amount of time dropped.
Return type:rhythm.lib.Measure

Zero out the Chronometer for the given subject.

In cases where consumed time should be skipped for the subsequent track operation, this method can be used to cause the consumed time to not be added to the tracked time.

Notably, zero is useful in cases where flow can be paused and unpaused.

class rhythm.libflow.Specificaton[source]

Bases: builtins.tuple

Structure used to define the throughtput for enforcing rate requirements

maximum[source]

The maximum transfer rate.

minimum[source]

The minimum transfer rate.

position(rate)[source]

Where the given rate falls within the designated range.

recoverable(rate, remainder)[source]

Given the current rate and the remainder of time, calculate whether or not its possible to come back and meet the minimum requirement within the remainder.

replace(**kw)[source]

Create a new Specification from the instance with the given keywords as overrides to the fields.

window[source]

The window

rhythm.libflow.maximum_time(current_rate, target_rate)[source]

Determine the rest time for a rate exceeding a maximum.

Given the case where a tracked flow is exceeding a configured maximum, calculate the necessary time that much elapse at a rate of zero before the flow will be at the maximum.

rhythm.libflow.minimum_units(current_rate, target_rate)[source]

Determine the increase in units necessary to achieve the target_rate.

Given the case where the current rate falls below a configured minimum, calculate the necessary rate increase required for the minimum to be achieved. This is a simple difference.

Using this difference in with the identification of the maximum possible throughput, one can determine whether or not it is possible for a rate increase to once again fall above the minimum within a given timeframe.

rhythm.libfs

Variants of the file systems interfaces yielding UNIX timestamps.

rhythm.libfs.fstat(fileno)[source]

Call to os.fstat transforming local UNIX times into rhythm.lib.Timestamp instances relative to UTC.

rhythm.libfs.lstat(path)[source]

Call to os.lstat transforming local UNIX times into rhythm.lib.Timestamp instances relative to UTC.

rhythm.libfs.stat(path)[source]

Call to os.stat transforming local UNIX times into rhythm.lib.Timestamp instances relative to UTC.

rhythm.abstract

Abstract base classes for time measures and points.

The inheritance hierarchy can get messy. These ABCs help to keep the inheritance under control and provide easy access to the APIs.

class rhythm.abstract.Clock[source]

Bases: builtins.object

“Clock instances” are a collection of clock based tools.

adjust(*args, **kw)[source]

Adjust the demotic clock according to the given measure.

delta()[source]

Construct a new iterator to the measure of time that has elapsed since the previous iteration of the returned object. If it is the first iteration, zero must be returned.

demotic()[source]

Return a snapshot of the clock in wall clock time according to the UTC timezone.

In contrast to monotonic.

meter()[source]

Returns an iterator to the total measure of time that has elapsed since the first iteration of the returned object.

If it is the first iteration, zero must be returned.

periods(quantity)[source]

Construct a new iterator yielding a pair, (count, remainder). Where the count is the number of times that the period has passed since the last iteration and the remainder is the amount of time until another has elapsed.

Period iterators are primarily used to poll for chunks of elapsed time. Whereas, delta() iterators only offer the finest grain available.

sleep(quantity)[source]

Sleep, block the processing of code according to the given measure of time.

sleeper()[source]

Create an object that sleeps for a designated period, but can be disturbed with precision at a designated frequency.

The returned object is an iterable that will sleep when iterated returning the amount of time that was spent sleeping.

stopwatch()[source]

Return a context manager that measures the amount of time that has elapsed since the invocation of __enter__(). The yielded object is a reference to the elapsed time and can be referenced prior to the exit of the context manager.

Once __exit__() is called, the elapsed time must no longer be measured and the result is subsequently consistent.

unit[source]

The precision of the clock and its methods.

Hopefully, nanoseconds or microseconds.

class rhythm.abstract.Measure[source]

Bases: rhythm.abstract.Range

An abstract quantity time. Usually, identified as a Scalar quantity unless subclassed.

decrease(*units, **parts)[source]
Parameters:
  • units – Variable number of Measure instances.
  • parts – Variable keywords whose keys designate the unit.

Decrease the measurement, repositioning the stop.

Returns a new Measure instance whose value is self decreased by the given parameters.

This is equivalent to:

neg_units = [-unit for unit in units]
neg_parts = {k:-v for (k,v) in parts}

assert self.decrease(*units, **parts) == self.of(self, *neg_units, **neg_parts)
increase(*units, **parts)[source]
Parameters:
  • units – Variable number of Measure instances.
  • parts – Variable keywords whose keys designate the unit.

Increase the measurement, repositioning the stop.

Returns a new Measure instance whose value is self increased by the given parameters.

This is equivalent to:

assert self.increase(*units, **parts) == self.of(self, *units, **parts)
magnitude[source]

The magnitude of the Time instance. For Measures, this is their integer value:

assert int(measure) == measure.magnitude
name[source]

Name of the unit of time. Normally equal to rhythm.abstract.Time.unit, but potentially different in cases where the proper name is not an identifier.

classmethod of(type, *times, **parts)[source]
Parameters:
  • times (rhythm.abstract.Time) – A sequence of time instances.
  • parts – Keyword names designate the unit of the corresponding value. The time

context dictates what that is. :type parts: int

Create an instance of the type from the sum of the quantities specified by units and parts:

measure = rhythm.lib.Measure.of(hour = 33, microsecond = 44)
select(part, of=None, align=0)[source]
Parameters:
  • part (str) – The unit whose count is to be returned.
  • of (str) – The unit whose total wholes are subtracted from self in order to find the correct total parts.
  • align – How to align the given part. Trivially, this is a difference that

is applied prior to removing wholes: value = self - align. :type align: int

Extract the number of complete parts designated by part after the last complete whole, of, with respect to the alignment, align.

The result is a Python int or an arbitrary object given that a Container part is referenced.

Common cases:

h = x.select('hour', 'day')
m = x.select('minute', 'hour')
s = x.select('second', 'minute')
u = x.select('microsecond', 'second')
start[source]

For Measure instances, this property must be zero.

assert measure.start == 0
stop[source]

For Measure instances, this property must be the instance, self:

assert measure.stop is measure
truncate(unit)[source]
Parameters:unit (str) – The minimum unit size to allow in the new time instance.
Returns:The adjust time instance.
Return type:Time

Truncates the time instance to the specified boundary: remove units smaller than the specified unit.

unit[source]

Identifier of the unit of time–usually the english name.

This must be a str where str(unit).isidentifier() is True.

update(part, replacement, of=None, align=0)[source]
Parameters:
  • part (str) – The name of the Part unit to set.
  • replacement (int) – The new value to set.
  • of (str) – The name of the Whole unit that defines the boundary of the part.
  • align (int) – Defaults to zero; the adjustment applied to the boundary.
Returns:

The adjusted time instance.

Return type:

Time

Construct and return a new instance adjusted by the difference between the selected part and the given value with respect to the specified alignment.

The following holds true:

updated = pit.update(part, replacement, of, align)
adjusted = this.adjust(**{part: replacement - pit.select(part, of, align)})
assert updated == adjusted

It’s existence as an interface is due to its utility.

class rhythm.abstract.Point[source]

Bases: rhythm.abstract.Range

A Point in Time, PiT; a Measure relative to an understood datum.

Points are an extension of Measures.

They isolate a position in time with a magnitude of one unit.

The use of magnitudes on Points is purely practical as leveraging this with Earth-Day units is far to useful to dismiss.

Measure[source]

The Point’s corresponding scalar class used to measure deltas. This may not be the Point’s direct superclass, but the following must hold true:

assert isinstance(point, point.Measure)
elapse[source]

Returns an adjusted measure in time by the given arguments and keywords.

Essentially, this is a call to the rhythm.abstract.Measure.of() method with the instance as the first parameter.

This is shorthand for T.of(T, *units, **parts).

magnitude[source]

The magnitude of the Point. For Points, this must be one:

assert pit.magnitude == 1
measure(pit)[source]

Return the measurement, Measure instance, between self and the given point in time. The delta between the two points.

rollback(*units, **parts)[source]

The point in time that occurred the given number of units before this point. The functionality is like Scalar.adjust(), but negates the parameters.

The method’s implementation must hold the following properties:

pit == (pit.ago(*measures, **units)).elapse(*measures, **units)

Where pit is an arbitrary Point, measures is a sequence of compatible Scalar instances, and units is a mapping of unit names to values.

start[source]

Points must return the instance; self:

assert pit.start is pit
stop[source]

The next Point according to the unit:

assert point.stop == point.elapse(point.Measure(1))
class rhythm.abstract.Range[source]

Bases: rhythm.abstract.Time

The representation of the span between two quantities.

Often, time quantities are treated as ranges, so rhythm makes all time types ranges for practical purposes.

magnitude[source]

The size of the Range in terms of the start.

start[source]

The beginning of the range.

stop[source]

The end of the range. Normally, stop is treated in a non-inclusive manner.

class rhythm.abstract.Time[source]

Bases: builtins.object

The abstract base class for all Time related types.

rhythm.libunit

Defines the time Context that constructs unit types and manages their relationship to other unit types.

The contents of this module are largely the mechanics under the hood and should not be used directly.

Danger

NOTHING IN THIS FILE SHOULD BE RELIED UPON.

Danger

THESE INTERFACES ARE SUBJECT TO CHANGE WITHOUT WARNING

class rhythm.libunit.Context[source]

Bases: builtins.object

A container for time units and transformations.

Warning

The APIs here are subject to change.

bridge(from_unit, to_unit, transformer)[source]

Note a “bridge” between two units.

In the case where a unit cannot not be resolved from its definitions, bridges can be used to perform the conversion.

compose(*args, **kwds)[source]

Compose two ratios into another so that the from_unit can be converted into the to_unit.

convert(from_unit, to_unit, value)[source]

Convert the value into to_unit from the from_unit.

declare(id, datum)[source]

Declare a fundamental unit for use in a context.

All defined, rhythm.libunit.Context.define(), units are defined in terms of a declared unit.

define(id, term, exponent, base=10)[source]

Defines a Unit in terms of another unit.

measure_factory(id, qname, Class=<class 'rhythm.libunit.Measure'>, name=None, address=None)[source]

Construct a measure with the designated unit identifier and class.

point_factory(Measure, qname, Class=<class 'rhythm.libunit.Point'>, point_magnitude=1)[source]

Construct a Point class from the given scalar.

class rhythm.libunit.Range[source]

Bases: builtins.tuple

A range between two points, inclusive on the start, but non-inclusive on the end.

If the start is greater than the end, the direction is implied to be negative.

points(step=None)[source]

Iterate through all the points between range according to the given step.

class rhythm.libunit.Unit[source]

Bases: builtins.int

The base class for Measures and Points subclasses across all Time Contexts.

rhythm.libunit.standard_context(qname)[source]

Construct the standard time context from the modules in rhythm.

rhythm.libzone

Timezone support.

class rhythm.libzone.Offset[source]

Bases: builtins.tuple

Offsets are constructed by a tuple of the form: (offset, abbreviation, type). Primarily, the type signifies whether or not the offset is daylight savings or not.

Offset instances are usually extracted from Zone objects which build a sequence of transitions for subsequent searching.

classmethod from_tzinfo(typ, tzinfo)[source]

Construct a Zone instance from a rhythm.tzif.tzinfo tuple.

is_dst[source]

Returns: self.type == ‘dst’

iso(pit)[source]

Return the offset-qualified ISO representation of the given point in time.

class rhythm.libzone.Zone(transitions, offsets, default, leaps, name)[source]

Bases: builtins.object

Zones consist of a sequence of transition times whose ranges correspond to a particular offset.

A mapping of transition times to their corresponding offset.

Zone instances manage the selection of a particular Offset.

find(pit)[source]
Parameters:pit – The timestamp to use to find an offset with.
Returns:An offset for the timestamp according to the Zone’s transition times.
Return type:Offset

Get the appropriate offset in the zone for a given Point In Time, pit.

If the pit does not fall within a known range, the default will be returned.

localize(pit)[source]
Parameters:pit – The timestamp to localize.
Returns:The localized timestamp.
Return type:rhythm.abstract.Point

Given a pit, return the localized version according to the zone’s transitions.

The given Point In Time is expected to have a perspective consistent with the zone’s transition times. (In the same zone.)

normalize(offset, pit)[source]
Parameters:
  • offset – The offset of the pit.
  • pit – The localized point in time to normalize.
Returns:

The re-localized pit and it’s new offset in a tuple.

Return type:

(rhythm.abstract.Point, Offset)

This function should be used in cases where adjustments are being made to an already zoned point in time. Once the adjustments are complete, the point should be normalized in order to properly represent the local point.

If no change is necessary, the exact, given pit will be returned.

slice(start, stop)[source]
Parameters:
Returns:

A sequence of offsets, transitions, that have occurred during the period.

Return type:

[Offset]

Get a slice of transition points and time zone offsets relative to a given start and stop.

rhythm.libformat

Format and parse datetime strings.

Primarily this module exposes two functions: rhythm.libformat.parser(), rhythm.libformat.formatter(). These functions provide access to datetime formats defined by a standard or deemed common enough to merit a builtin implementation.

Note

The near future will bring a strptime and strftime implementation.

While formatting PiTs can usually occur without error, parsing them from strings can result in a variety of errors. The parsers available in rhythm.libformat can raise the following errors:

rhythm.libformat.ParseError
This error is raised in cases where the string could not be separated by the known delimiters of the format.
rhythm.libformat.StructureError
This error is raised when the parts of the string could not be converted. Normally, this means a given field was not an integer or the field was not found in a mapping resolving the field’s value.
rhythm.libformat.IntegrityError
This error is raised when the parts of the timestamp contradict each other. This error is only possible in formats that contain redundant information about the timestamp.
exception rhythm.libformat.IntegrityError(source, struct, tuple, format=None)[source]

Bases: rhythm.libformat.Error

The exception raised when a parsed point in time is not consistent.

Notably, in the RFC format, there are portions specifying intersecting parts of a timestamp. (The day of week field is arguably superfluous.)

exception rhythm.libformat.ParseError(source, format=None)[source]

Bases: rhythm.libformat.Error

The exception raised when the format of the datetime could not be parsed.

exception rhythm.libformat.StructureError(source, struct, format=None)[source]

Bases: rhythm.libformat.Error

The exception raised when the structure of a parsed format could not be transformed.

rhythm.libformat.formatter(fmt, _deref=<built-in method get of dict object at 0x104011b90>)[source]

Given a format idenifier, return the function that can be used to format the Point in time.

rhythm.libformat.parser(fmt, _deref=<built-in method get of dict object at 0x104011b90>, _getn1=<operator.itemgetter object at 0x104094550>)[source]

Given a format idenifier, return the function that can be used to parse the formatted string into a Point instance.