From e26a0c4f1acc82b4609aeace7590575853c62307 Mon Sep 17 00:00:00 2001 From: narimiran Date: Mon, 11 Feb 2019 12:36:51 +0100 Subject: [PATCH] better docs: times --- lib/pure/times.nim | 120 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 93 insertions(+), 27 deletions(-) diff --git a/lib/pure/times.nim b/lib/pure/times.nim index 260850a0ef..2b1c4eb03f 100644 --- a/lib/pure/times.nim +++ b/lib/pure/times.nim @@ -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.