[add+change] Added toDurationParts proc to convert Duration to array[FixedTimeUnit, int64] of it's human-readable parts, use it in $Duration
This commit is contained in:
parent
08d1b5892b
commit
a573577cdc
1 changed files with 53 additions and 22 deletions
|
|
@ -183,6 +183,9 @@ type
|
||||||
## The point in time represented by ``ZonedTime`` is ``adjTime + utcOffset.seconds``.
|
## The point in time represented by ``ZonedTime`` is ``adjTime + utcOffset.seconds``.
|
||||||
isDst*: bool ## Determines whether DST is in effect.
|
isDst*: bool ## Determines whether DST is in effect.
|
||||||
|
|
||||||
|
DurationParts* = array[FixedTimeUnit, int64] # Array of Duration parts starts
|
||||||
|
|
||||||
|
|
||||||
{.deprecated: [TMonth: Month, TWeekDay: WeekDay, TTime: Time,
|
{.deprecated: [TMonth: Month, TWeekDay: WeekDay, TTime: Time,
|
||||||
TTimeInterval: TimeInterval, TTimeInfo: DateTime, TimeInfo: DateTime].}
|
TTimeInterval: TimeInterval, TTimeInfo: DateTime, TimeInfo: DateTime].}
|
||||||
|
|
||||||
|
|
@ -451,44 +454,55 @@ const DurationZero* = initDuration() ## \
|
||||||
## doAssert initDuration(seconds = 1) > DurationZero
|
## doAssert initDuration(seconds = 1) > DurationZero
|
||||||
## doAssert initDuration(seconds = 0) == DurationZero
|
## doAssert initDuration(seconds = 0) == DurationZero
|
||||||
|
|
||||||
proc `$`*(dur: Duration): string =
|
proc toParts*(dur: Duration): DurationParts =
|
||||||
## Human friendly string representation of ``dur``.
|
## Converts a duration into an array consisting of fixed time units.
|
||||||
|
##
|
||||||
|
## Each value in the array gives information about a specific unit of
|
||||||
|
## time, for example ``result[Days]`` gives a count of days.
|
||||||
|
##
|
||||||
|
## This procedure is useful for converting ``Duration`` values to strings.
|
||||||
runnableExamples:
|
runnableExamples:
|
||||||
doAssert $initDuration(seconds = 2) == "2 seconds"
|
var dp = toParts(initDuration(weeks=2, days=1))
|
||||||
doAssert $initDuration(weeks = 1, days = 2) == "1 week and 2 days"
|
doAssert dp[Days] == 1
|
||||||
doAssert $initDuration(hours = 1, minutes = 2, seconds = 3) == "1 hour, 2 minutes, and 3 seconds"
|
doAssert dp[Weeks] == 2
|
||||||
doAssert $initDuration(milliseconds = -1500) == "-1 second and -500 milliseconds"
|
dp = toParts(initDuration(days = -1))
|
||||||
var parts = newSeq[string]()
|
doAssert dp[Days] == -1
|
||||||
|
|
||||||
var remS = dur.seconds
|
var remS = dur.seconds
|
||||||
var remNs = dur.nanosecond.int
|
var remNs = dur.nanosecond.int
|
||||||
|
|
||||||
# Normally ``nanoseconds`` should always be positive, but
|
# Ensure the same sign for seconds and nanoseconds
|
||||||
# that makes no sense when printing.
|
if remS < 0 and remNs != 0:
|
||||||
if remS < 0:
|
|
||||||
remNs -= convert(Seconds, Nanoseconds, 1)
|
remNs -= convert(Seconds, Nanoseconds, 1)
|
||||||
remS.inc 1
|
remS.inc 1
|
||||||
|
|
||||||
const unitStrings: array[FixedTimeUnit, string] = [
|
|
||||||
"nanosecond", "microsecond", "millisecond", "second", "minute", "hour", "day", "week"
|
|
||||||
]
|
|
||||||
|
|
||||||
for unit in countdown(Weeks, Seconds):
|
for unit in countdown(Weeks, Seconds):
|
||||||
let quantity = convert(Seconds, unit, remS)
|
let quantity = convert(Seconds, unit, remS)
|
||||||
remS = remS mod convert(unit, Seconds, 1)
|
remS = remS mod convert(unit, Seconds, 1)
|
||||||
|
|
||||||
if quantity.abs == 1:
|
result[unit] = quantity
|
||||||
parts.add $quantity & " " & unitStrings[unit]
|
|
||||||
elif quantity != 0:
|
|
||||||
parts.add $quantity & " " & unitStrings[unit] & "s"
|
|
||||||
|
|
||||||
for unit in countdown(Milliseconds, Nanoseconds):
|
for unit in countdown(Milliseconds, Nanoseconds):
|
||||||
let quantity = convert(Nanoseconds, unit, remNs)
|
let quantity = convert(Nanoseconds, unit, remNs)
|
||||||
remNs = remNs mod convert(unit, Nanoseconds, 1)
|
remNs = remNs mod convert(unit, Nanoseconds, 1)
|
||||||
|
|
||||||
if quantity.abs == 1:
|
result[unit] = quantity
|
||||||
parts.add $quantity & " " & unitStrings[unit]
|
|
||||||
elif quantity != 0:
|
proc stringifyUnit*(value: int | int64, unit: string): string =
|
||||||
parts.add $quantity & " " & unitStrings[unit] & "s"
|
## Stringify time unit with it's name, lowercased
|
||||||
|
runnableExamples:
|
||||||
|
doAssert stringifyUnit(2, "Seconds") == "2 seconds"
|
||||||
|
doAssert stringifyUnit(1, "Years") == "1 year"
|
||||||
|
result = ""
|
||||||
|
result.add($value)
|
||||||
|
result.add(" ")
|
||||||
|
if abs(value) != 1:
|
||||||
|
result.add(unit.toLowerAscii())
|
||||||
|
else:
|
||||||
|
result.add(unit[0..^2].toLowerAscii())
|
||||||
|
|
||||||
|
proc humanizeParts(parts: seq[string]): string =
|
||||||
|
## Make date string parts human-readable
|
||||||
|
|
||||||
result = ""
|
result = ""
|
||||||
if parts.len == 0:
|
if parts.len == 0:
|
||||||
|
|
@ -502,6 +516,23 @@ proc `$`*(dur: Duration): string =
|
||||||
result.add part & ", "
|
result.add part & ", "
|
||||||
result.add "and " & parts[high(parts)]
|
result.add "and " & parts[high(parts)]
|
||||||
|
|
||||||
|
proc `$`*(dur: Duration): string =
|
||||||
|
## Human friendly string representation of ``Duration``.
|
||||||
|
runnableExamples:
|
||||||
|
doAssert $initDuration(seconds = 2) == "2 seconds"
|
||||||
|
doAssert $initDuration(weeks = 1, days = 2) == "1 week and 2 days"
|
||||||
|
doAssert $initDuration(hours = 1, minutes = 2, seconds = 3) == "1 hour, 2 minutes, and 3 seconds"
|
||||||
|
doAssert $initDuration(milliseconds = -1500) == "-1 second and -500 milliseconds"
|
||||||
|
var parts = newSeq[string]()
|
||||||
|
var numParts = toParts(dur)
|
||||||
|
|
||||||
|
for unit in countdown(Weeks, Nanoseconds):
|
||||||
|
let quantity = numParts[unit]
|
||||||
|
if quantity != 0.int64:
|
||||||
|
parts.add(stringifyUnit(quantity, $unit))
|
||||||
|
|
||||||
|
result = humanizeParts(parts)
|
||||||
|
|
||||||
proc `+`*(a, b: Duration): Duration {.operator.} =
|
proc `+`*(a, b: Duration): Duration {.operator.} =
|
||||||
## Add two durations together.
|
## Add two durations together.
|
||||||
runnableExamples:
|
runnableExamples:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue