Skip to content

Commit

Permalink
Add KDoc to StyledDuration
Browse files Browse the repository at this point in the history
  • Loading branch information
rock3r committed Feb 17, 2021
1 parent a8baf47 commit 4f75d01
Show file tree
Hide file tree
Showing 2 changed files with 128 additions and 3 deletions.
127 changes: 126 additions & 1 deletion src/main/kotlin/dev/stalla/model/StyledDuration.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,69 @@ import java.time.Duration
import kotlin.math.absoluteValue
import kotlin.math.pow

/**
* Represents a duration, expressed in one of the supported styles. Each supported style is
* represented by one of the concrete implementations of [StyledDuration].
*
* @see Seconds
* @see SecondsAndFraction
* @see HoursMinutesSeconds
* @see MinutesSeconds
*/
public sealed class StyledDuration {

/**
* Formats the duration value as a string in the style this instance.
*/
public abstract fun asFormattedString(): String

/**
* The underlying [Duration] value.
*
* Note that due to the way [Duration] represents values internally, the
* [Duration.seconds] and [Duration.nanos] values may seem incorrect even
* though they are representing the right value.
*/
public abstract val rawDuration: Duration

/**
* True when the duration value is less than `0:00:00.000`.
*
* @see Duration.isNegative
*/
public val isNegative: Boolean
get() = rawDuration.seconds < 0 || rawDuration.nano < 0
get() = rawDuration.isNegative

/**
* True when the duration value is exactly `0:00:00.000`.
*
* @see Duration.isZero
*/
public val isZero: Boolean
get() = rawDuration.isZero

/**
* True when the duration value is equal to or greater than than `0:00:00.000`.
*
* @see isZero
* @see isNegative
*/
public val isStrictlyPositive: Boolean
get() = !(isNegative || isZero)

final override fun toString(): String = "${javaClass.simpleName}(rawDuration: '$rawDuration', formatted: \"${asFormattedString()}\")"

/**
* A duration expressed in the style: `[-]S[.FFF]`.
*
* The negative symbol and fractional part are optional, and are omitted
* by [asFormattedString] when the duration is positive, and has no fractional
* part, respectively.
*
* The seconds can have as many digits as needed.
*
* @see StyledDuration.Factory.secondsAndFraction
*/
public data class SecondsAndFraction @InternalApi internal constructor(
public override val rawDuration: Duration
) : StyledDuration() {
Expand Down Expand Up @@ -66,6 +112,16 @@ public sealed class StyledDuration {
}
}

/**
* A duration expressed in the style: `[-]S`.
*
* The negative symbol is optional, and is omitted by [asFormattedString] when
* the duration is positive.
*
* The seconds can have as many digits as needed.
*
* @see StyledDuration.Factory.seconds
*/
public data class Seconds @InternalApi internal constructor(
public override val rawDuration: Duration
) : StyledDuration() {
Expand All @@ -76,6 +132,16 @@ public sealed class StyledDuration {
}
}

/**
* A duration expressed in the style: `[-]MM:SS`.
*
* The negative symbol is optional, and is omitted by [asFormattedString] when
* the duration is positive. Note that while the seconds are always formatted
* with two digits, the minutes may have one or two depending on their value.
* This means the duration 1 min 3 sec is formatted as `1:03`, not `01:03`.
*
* @see StyledDuration.Factory.minutesSeconds
*/
public data class MinutesSeconds @InternalApi internal constructor(
public override val rawDuration: Duration
) : StyledDuration() {
Expand All @@ -88,6 +154,17 @@ public sealed class StyledDuration {
}
}

/**
* A duration expressed in the style: `[-]HH:MM:SS`.
*
* The negative symbol is optional, and is omitted by [asFormattedString] when
* the duration is positive. Note that while the minutes and seconds are always
* formatted with two digits, the hours may have one or two depending on their
* value. This means the duration 1 hour, 2 min and 3 sec is formatted as
* `1:02:03`, not `01:02:03`.
*
* @see StyledDuration.Factory.hoursMinutesSeconds
*/
public data class HoursMinutesSeconds @InternalApi internal constructor(
public override val rawDuration: Duration
) : StyledDuration() {
Expand All @@ -110,6 +187,14 @@ public sealed class StyledDuration {
// Parses the format: [-]SS...[.FFF...]
private val plainSecondsRegex = "(-)?(\\d+)(?:\\.(\\d+))?".toRegex()

/**
* Parses the provided [rawValue] and returns the most appropriate
* type of [StyledDuration], representing the value and its style.
*
* @param rawValue The string representation of the instance.
* @return The instance matching [rawValue], or `null` if [rawValue]
* is not in any supported style.
*/
@JvmStatic
public override fun of(rawValue: String?): StyledDuration? {
if (rawValue.isNullOrBlank()) return null
Expand Down Expand Up @@ -159,6 +244,15 @@ public sealed class StyledDuration {
}
}

/**
* Creates an instance of [SecondsAndFraction] from the duration components.
*
* @param seconds The number of seconds. Must be positive.
* @param nano The nanoseconds (fractional part of the second). Must be positive.
* Should be `[0, 999_999_999]`.
* @param positive True when the duration is positive, false when it's negative.
* @return A new [SecondsAndFraction] instance representing the given duration.
*/
@JvmStatic
@JvmOverloads
public fun secondsAndFraction(seconds: Int = 0, nano: Long = 0, positive: Boolean = true): SecondsAndFraction {
Expand All @@ -169,6 +263,13 @@ public sealed class StyledDuration {
return SecondsAndFraction(Duration.parse(durationString))
}

/**
* Creates an instance of [Seconds] from the duration components.
*
* @param seconds The number of seconds. Must be positive.
* @param positive True when the duration is positive, false when it's negative.
* @return A new [Seconds] instance representing the given duration.
*/
@JvmStatic
@JvmOverloads
public fun seconds(seconds: Int = 0, positive: Boolean = true): Seconds {
Expand All @@ -177,6 +278,17 @@ public sealed class StyledDuration {
return Seconds(Duration.ofSeconds(seconds.toLong() * sign))
}

/**
* Creates an instance of [MinutesSeconds] from the duration components.
*
* Note that you should only use values of [minutes] and [seconds] up to `59`
* to avoid nasty bugs, but this method doesn't enforce that.
*
* @param minutes The number of minutes. Must be positive. Should be `[0, 59]`.
* @param seconds The number of seconds. Must be positive. Should be `[0, 59]`.
* @param positive True when the duration is positive, false when it's negative.
* @return A new [MinutesSeconds] instance representing the given duration.
*/
@JvmStatic
@JvmOverloads
public fun minutesSeconds(minutes: Int = 0, seconds: Int = 0, positive: Boolean = true): MinutesSeconds {
Expand All @@ -187,6 +299,19 @@ public sealed class StyledDuration {
return MinutesSeconds(rawDuration)
}

/**
* Creates an instance of [HoursMinutesSeconds] from the duration components.
*
* Note that you should only use values of [minutes] and [seconds] up to `59`,
* and up to `99` [hours] only to avoid nasty bugs, but this method doesn't
* enforce that.
*
* @param hours The number of hours. Must be positive. Should be `[0, 99]`.
* @param minutes The number of minutes. Must be positive. Should be `[0, 59]`.
* @param seconds The number of seconds. Must be positive. Should be `[0, 59]`.
* @param positive True when the duration is positive, false when it's negative.
* @return A new [HoursMinutesSeconds] instance representing the given duration.
*/
@JvmOverloads
public fun hoursMinutesSeconds(hours: Int = 0, minutes: Int = 0, seconds: Int = 0, positive: Boolean = true): HoursMinutesSeconds {
require(hours >= 0 && minutes >= 0 && seconds >= 0) { "Components cannot be negative" }
Expand Down
4 changes: 2 additions & 2 deletions src/main/kotlin/dev/stalla/model/TypeFactory.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ package dev.stalla.model

internal interface TypeFactory<out T> {
/**
* Factory method for the instance of matching the [rawValue] parameter.
* Factory method that returns the instance matching the [rawValue] parameter, if any.
*
* @param rawValue The string representation of the instance.
* @return The instance matching [rawValue], or null if no matching instance exists.
* @return The instance matching [rawValue], or `null` if no matching instance exists.
*/
fun of(rawValue: String?): T?
}

0 comments on commit 4f75d01

Please sign in to comment.