better docs: times

This commit is contained in:
narimiran
2019-02-11 12:36:51 +01:00
committed by Andreas Rumpf
parent 36f6f035ff
commit e26a0c4f1a

View File

@@ -130,7 +130,8 @@
Duration vs TimeInterval
----------------------------
The ``times`` module exports two similiar types that are both used to
represent some amount of time: ``Duration`` and ``TimeInterval``.
represent some amount of time: `Duration <#Duration>`_ and
`TimeInterval <#TimeInterval>`_.
This section explains how they differ and when one should be prefered over the
other (short answer: use ``Duration`` unless support for months and years is
needed).
@@ -302,9 +303,10 @@ type
## they should never be mutated directly. Doing so is unsafe and will
## result in the ``DateTime`` ending up in an invalid state.
##
## Instead of mutating the fields directly, use the ``Duration``
## and ``TimeInterval`` types for arithmetic and use the ``initDateTime``
## procedure for changing a specific field.
## Instead of mutating the fields directly, use the `Duration <#Duration>`_
## and `TimeInterval <#TimeInterval>`_ types for arithmetic and use the
## `initDateTime proc <#initDateTime,MonthdayRange,Month,int,HourRange,MinuteRange,SecondRange,NanosecondRange,Timezone>`_
## for changing a specific field.
nanosecond*: NanosecondRange ## The number of nanoseconds after the second,
## in the range 0 to 999_999_999.
second*: SecondRange ## The number of seconds after the minute,
@@ -334,7 +336,10 @@ type
## ``-3600``).
Duration* = object ## Represents a fixed duration of time, meaning a duration
## that has constant length independent of the context.
## that has constant length independent of the context.
##
## To create a new ``Duration``, use `initDuration proc
## <#initDuration,int64,int64,int64,int64,int64,int64,int64,int64>`_.
seconds: int64
nanosecond: NanosecondRange
@@ -348,15 +353,20 @@ type
TimeInterval* = object ## \
## Represents a non-fixed duration of time. Can be used to add and
## subtract non-fixed time units from a ``DateTime`` or ``Time``.
## subtract non-fixed time units from a `DateTime <#DateTime>`_ or
## `Time <#Time>`_.
##
## Create a new ``TimeInterval`` with `initTimeInterval proc
## <#initTimeInterval,int,int,int,int,int,int,int,int,int,int>`_.
##
## Note that ``TimeInterval`` doesn't represent a fixed duration of time,
## since the duration of some units depend on the context (e.g a year
## can be either 365 or 366 days long). The non-fixed time units are
## years, months, days and week.
##
## Note that ``TimeInterval``'s returned from the ``times`` module are
## never normalized. If you want to normalize a time unit, ``Duration``
## should be used instead.
## never normalized. If you want to normalize a time unit,
## `Duration <#Duration>`_ should be used instead.
nanoseconds*: int ## The number of nanoseconds
microseconds*: int ## The number of microseconds
milliseconds*: int ## The number of milliseconds
@@ -369,7 +379,7 @@ type
years*: int ## The number of years
Timezone* = ref object ## \
## Timezone interface for supporting ``DateTime``'s of arbritary
## Timezone interface for supporting `DateTime <#DateTime>`_\s of arbritary
## timezones. The ``times`` module only supplies implementations for the
## systems local time and UTC.
zonedTimeFromTimeImpl: proc (x: Time): ZonedTime
@@ -451,7 +461,7 @@ proc nanosecond*(time: Time): NanosecondRange =
proc initDuration*(nanoseconds, microseconds, milliseconds,
seconds, minutes, hours, days, weeks: int64 = 0): Duration =
## Create a new duration.
## Create a new `Duration <#Duration>`_.
runnableExamples:
let dur = initDuration(seconds = 1, milliseconds = 1)
doAssert dur.milliseconds == 1
@@ -473,53 +483,72 @@ proc initDuration*(nanoseconds, microseconds, milliseconds,
proc weeks*(dur: Duration): int64 {.inline.} =
## Number of whole weeks represented by the duration.
runnableExamples:
let dur = initDuration(weeks = 1, days = 2, hours = 3, minutes = 4)
doAssert dur.weeks == 1
convert(Seconds, Weeks, dur.seconds)
proc days*(dur: Duration): int64 {.inline.} =
## Number of whole days represented by the duration.
runnableExamples:
let dur = initDuration(weeks = 1, days = 2, hours = 3, minutes = 4)
doAssert dur.days == 9
convert(Seconds, Days, dur.seconds)
proc minutes*(dur: Duration): int64 {.inline.} =
## Number of whole minutes represented by the duration.
convert(Seconds, Minutes, dur.seconds)
proc hours*(dur: Duration): int64 {.inline.} =
## Number of whole hours represented by the duration.
runnableExamples:
let dur = initDuration(days = 1, hours = 2, minutes = 3)
doAssert dur.hours == 26
convert(Seconds, Hours, dur.seconds)
proc minutes*(dur: Duration): int64 {.inline.} =
## Number of whole minutes represented by the duration.
runnableExamples:
let dur = initDuration(days = 1, hours = 2, minutes = 3)
doAssert dur.minutes == 1563
convert(Seconds, Minutes, dur.seconds)
proc seconds*(dur: Duration): int64 {.inline.} =
## Number of whole seconds represented by the duration.
runnableExamples:
let dur = initDuration(minutes = 10, seconds = 30)
doAssert dur.seconds == 630
dur.seconds
proc milliseconds*(dur: Duration): int {.inline.} =
## Number of whole milliseconds represented by the **fractional**
## part of the duration.
runnableExamples:
let dur = initDuration(seconds = 1, milliseconds = 1)
doAssert dur.milliseconds == 1
let dur = initDuration(minutes = 5, seconds = 6, milliseconds = 7,
microseconds = 8, nanoseconds = 9)
doAssert dur.milliseconds == 7
convert(Nanoseconds, Milliseconds, dur.nanosecond)
proc microseconds*(dur: Duration): int {.inline.} =
## Number of whole microseconds represented by the **fractional**
## part of the duration.
runnableExamples:
let dur = initDuration(seconds = 1, microseconds = 1)
doAssert dur.microseconds == 1
let dur = initDuration(minutes = 5, seconds = 6, milliseconds = 7,
microseconds = 8, nanoseconds = 9)
doAssert dur.microseconds == 7008
convert(Nanoseconds, Microseconds, dur.nanosecond)
proc nanoseconds*(dur: Duration): int {.inline.} =
## Number of whole nanoseconds represented by the **fractional**
## part of the duration.
runnableExamples:
let dur = initDuration(seconds = 1, nanoseconds = 1)
doAssert dur.nanoseconds == 1
let dur = initDuration(minutes = 5, seconds = 6, milliseconds = 7,
microseconds = 8, nanoseconds = 9)
doAssert dur.nanoseconds == 7008009
dur.nanosecond
proc fractional*(dur: Duration): Duration {.inline.} =
## The fractional part of duration, as a duration.
runnableExamples:
let dur = initDuration(seconds = 1, nanoseconds = 5)
doAssert dur.fractional == initDuration(nanoseconds = 5)
let dur = initDuration(minutes = 5, seconds = 6, milliseconds = 7,
microseconds = 8, nanoseconds = 9)
doAssert dur.fractional == initDuration(milliseconds = 7, microseconds = 8, nanoseconds = 9)
initDuration(nanoseconds = dur.nanosecond)
proc fromUnix*(unix: int64): Time
@@ -551,11 +580,17 @@ proc toWinTime*(t: Time): int64 =
proc isLeapYear*(year: int): bool =
## Returns true if ``year`` is a leap year.
runnableExamples:
doAssert isLeapYear(2000)
doAssert not isLeapYear(1900)
year mod 4 == 0 and (year mod 100 != 0 or year mod 400 == 0)
proc getDaysInMonth*(month: Month, year: int): int =
## Get the number of days in ``month`` of ``year``.
# http://www.dispersiondesign.com/articles/time/number_of_days_in_a_month
runnableExamples:
doAssert getDaysInMonth(mFeb, 2000) == 29
doAssert getDaysInMonth(mFeb, 2001) == 28
case month
of mFeb: result = if isLeapYear(year): 29 else: 28
of mApr, mJun, mSep, mNov: result = 30
@@ -563,6 +598,9 @@ proc getDaysInMonth*(month: Month, year: int): int =
proc getDaysInYear*(year: int): int =
## Get the number of days in a ``year``
runnableExamples:
doAssert getDaysInYear(2000) == 366
doAssert getDaysInYear(2001) == 365
result = 365 + (if isLeapYear(year): 1 else: 0)
proc assertValidDate(monthday: MonthdayRange, month: Month, year: int)
@@ -609,6 +647,11 @@ proc getDayOfYear*(monthday: MonthdayRange, month: Month, year: int):
YeardayRange {.tags: [], raises: [], benign.} =
## Returns the day of the year.
## Equivalent with ``initDateTime(monthday, month, year, 0, 0, 0).yearday``.
runnableExamples:
doAssert getDayOfYear(1, mJan, 2000) == 0
doAssert getDayOfYear(10, mJan, 2000) == 9
doAssert getDayOfYear(10, mFeb, 2000) == 40
assertValidDate monthday, month, year
const daysUntilMonth: array[Month, int] =
[0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334]
@@ -624,6 +667,10 @@ proc getDayOfWeek*(monthday: MonthdayRange, month: Month, year: int): WeekDay
{.tags: [], raises: [], benign.} =
## Returns the day of the week enum from day, month and year.
## Equivalent with ``initDateTime(monthday, month, year, 0, 0, 0).weekday``.
runnableExamples:
doAssert getDayOfWeek(13, mJun, 1990) == dWed
doAssert $getDayOfWeek(13, mJun, 1990) == "Wednesday"
assertValidDate monthday, month, year
# 1970-01-01 is a Thursday, we adjust to the previous Monday
let days = toEpochday(monthday, month, year) - 3
@@ -670,6 +717,7 @@ proc toParts*(dur: Duration): DurationParts =
var dp = toParts(initDuration(weeks = 2, days = 1))
doAssert dp[Days] == 1
doAssert dp[Weeks] == 2
doAssert dp[Minutes] == 0
dp = toParts(initDuration(days = -1))
doAssert dp[Days] == -1
@@ -766,24 +814,32 @@ proc `<`*(a, b: Duration): bool {.operator.} =
runnableExamples:
doAssert initDuration(seconds = 1) < initDuration(seconds = 2)
doAssert initDuration(seconds = -2) < initDuration(seconds = 1)
doAssert initDuration(seconds = -2).abs < initDuration(seconds = 1).abs == false
ltImpl(a, b)
proc `<=`*(a, b: Duration): bool {.operator.} =
lqImpl(a, b)
proc `==`*(a, b: Duration): bool {.operator.} =
runnableExamples:
let
d1 = initDuration(weeks = 1)
d2 = initDuration(days = 7)
doAssert d1 == d2
eqImpl(a, b)
proc `*`*(a: int64, b: Duration): Duration {.operator.} =
## Multiply a duration by some scalar.
runnableExamples:
doAssert 5 * initDuration(seconds = 1) == initDuration(seconds = 5)
doAssert 3 * initDuration(minutes = 45) == initDuration(hours = 2, minutes = 15)
normalize[Duration](a * b.seconds, a * b.nanosecond)
proc `*`*(a: Duration, b: int64): Duration {.operator.} =
## Multiply a duration by some scalar.
runnableExamples:
doAssert initDuration(seconds = 1) * 5 == initDuration(seconds = 5)
doAssert initDuration(minutes = 45) * 3 == initDuration(hours = 2, minutes = 15)
b * a
proc `div`*(a: Duration, b: int64): Duration {.operator.} =
@@ -791,18 +847,23 @@ proc `div`*(a: Duration, b: int64): Duration {.operator.} =
runnableExamples:
doAssert initDuration(seconds = 3) div 2 ==
initDuration(milliseconds = 1500)
doAssert initDuration(minutes = 45) div 30 ==
initDuration(minutes = 1, seconds = 30)
doAssert initDuration(nanoseconds = 3) div 2 ==
initDuration(nanoseconds = 1)
let carryOver = convert(Seconds, Nanoseconds, a.seconds mod b)
normalize[Duration](a.seconds div b, (a.nanosecond + carryOver) div b)
proc initTime*(unix: int64, nanosecond: NanosecondRange): Time =
## Create a ``Time`` from a unix timestamp and a nanosecond part.
## Create a `Time <#Time>`_ from a unix timestamp and a nanosecond part.
result.seconds = unix
result.nanosecond = nanosecond
proc `-`*(a, b: Time): Duration {.operator, extern: "ntDiffTime".} =
## Computes the duration between two points in time.
runnableExamples:
doAssert initTime(1000, 100) - initTime(500, 20) ==
initDuration(minutes = 8, seconds = 20, nanoseconds = 80)
subImpl[Duration](a, b)
proc `+`*(a: Time, b: Duration): Time {.operator, extern: "ntAddTime".} =
@@ -819,6 +880,8 @@ proc `-`*(a: Time, b: Duration): Time {.operator, extern: "ntSubTime".} =
proc `<`*(a, b: Time): bool {.operator, extern: "ntLtTime".} =
## Returns true iff ``a < b``, that is iff a happened before b.
runnableExamples:
doAssert initTime(50, 0) < initTime(99, 0)
ltImpl(a, b)
proc `<=`*(a, b: Time): bool {.operator, extern: "ntLeTime".} =
@@ -1134,7 +1197,7 @@ proc now*(): DateTime {.tags: [TimeEffect], benign.} =
proc initTimeInterval*(nanoseconds, microseconds, milliseconds,
seconds, minutes, hours,
days, weeks, months, years: int = 0): TimeInterval =
## Creates a new ``TimeInterval``.
## Creates a new `TimeInterval <#TimeInterval>`_.
##
## This proc doesn't perform any normalization! For example,
## ``initTimeInterval(hours = 24)`` and ``initTimeInterval(days = 1)`` are
@@ -1342,7 +1405,7 @@ proc initDateTime*(monthday: MonthdayRange, month: Month, year: int,
hour: HourRange, minute: MinuteRange, second: SecondRange,
nanosecond: NanosecondRange,
zone: Timezone = local()): DateTime =
## Create a new ``DateTime`` in the specified timezone.
## Create a new `DateTime <#DateTime>`_ in the specified timezone.
runnableExamples:
let dt1 = initDateTime(30, mMar, 2017, 00, 00, 00, 00, utc())
doAssert $dt1 == "2017-03-30T00:00:00Z"
@@ -1362,7 +1425,7 @@ proc initDateTime*(monthday: MonthdayRange, month: Month, year: int,
proc initDateTime*(monthday: MonthdayRange, month: Month, year: int,
hour: HourRange, minute: MinuteRange, second: SecondRange,
zone: Timezone = local()): DateTime =
## Create a new ``DateTime`` in the specified timezone.
## Create a new `DateTime <#DateTime>`_ in the specified timezone.
runnableExamples:
let dt1 = initDateTime(30, mMar, 2017, 00, 00, 00, utc())
doAssert $dt1 == "2017-03-30T00:00:00Z"
@@ -1663,7 +1726,10 @@ type
Lit
TimeFormat* = object ## Represents a format for parsing and printing
## time types.
## time types.
##
## To create a new ``TimeFormat`` use `initTimeFormat proc
## <#initTimeFormat,string>`_.
patterns: seq[byte] ## \
## Contains the patterns encoded as bytes.
## Literal values are encoded in a special way.