taler-android

Android apps for GNU Taler (wallet, PoS, cashier)
Log | Files | Refs | README | LICENSE

Time.kt (3806B)


      1 /*
      2  * This file is part of GNU Taler
      3  * (C) 2020 Taler Systems S.A.
      4  *
      5  * GNU Taler is free software; you can redistribute it and/or modify it under the
      6  * terms of the GNU General Public License as published by the Free Software
      7  * Foundation; either version 3, or (at your option) any later version.
      8  *
      9  * GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
     10  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
     11  * A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
     12  *
     13  * You should have received a copy of the GNU General Public License along with
     14  * GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
     15  */
     16 
     17 package net.taler.common
     18 
     19 import kotlinx.serialization.SerialName
     20 import kotlinx.serialization.Serializable
     21 import kotlinx.serialization.builtins.serializer
     22 import kotlinx.serialization.json.JsonElement
     23 import kotlinx.serialization.json.JsonPrimitive
     24 import kotlinx.serialization.json.JsonTransformingSerializer
     25 import kotlinx.serialization.json.contentOrNull
     26 import kotlinx.serialization.json.jsonPrimitive
     27 import kotlinx.serialization.json.longOrNull
     28 import kotlin.math.max
     29 
     30 @Serializable
     31 data class Timestamp(
     32     @SerialName("t_s")
     33     @Serializable(NeverSerializer::class)
     34     private val s: Long,
     35 ) : Comparable<Timestamp> {
     36 
     37     companion object {
     38         private const val NEVER: Long = -1
     39         fun now(): Timestamp = fromMillis(System.currentTimeMillis())
     40         fun never(): Timestamp = Timestamp(NEVER)
     41         fun fromMillis(ms: Long) = Timestamp(ms / 1000L)
     42     }
     43 
     44     val ms: Long = s * 1000L
     45 
     46     operator fun minus(other: Timestamp): RelativeTime = when {
     47         ms == NEVER -> RelativeTime.fromMillis(RelativeTime.FOREVER)
     48         other.ms == NEVER -> throw Error("Invalid argument for timestamp comparison")
     49         ms < other.ms -> RelativeTime.fromMillis(0)
     50         else -> RelativeTime.fromMillis(ms - other.ms)
     51     }
     52 
     53     operator fun plus(other: RelativeTime): Timestamp = when {
     54         ms == NEVER -> this
     55         other.ms == RelativeTime.FOREVER -> never()
     56         else -> fromMillis(ms + other.ms)
     57     }
     58 
     59     operator fun minus(other: RelativeTime): Timestamp = when {
     60         ms == NEVER -> this
     61         other.ms == RelativeTime.FOREVER -> fromMillis(0)
     62         else -> fromMillis(max(0, ms - other.ms))
     63     }
     64 
     65     override fun compareTo(other: Timestamp): Int {
     66         return if (ms == NEVER) {
     67             if (other.ms == NEVER) 0
     68             else 1
     69         } else {
     70             if (other.ms == NEVER) -1
     71             else ms.compareTo(other.ms)
     72         }
     73     }
     74 
     75 }
     76 
     77 @Serializable
     78 data class RelativeTime(
     79     /**
     80      * Duration in microseconds or "forever" to represent an infinite duration.
     81      * Numeric values are capped at 2^53 - 1 inclusive.
     82      */
     83     @SerialName("d_us")
     84     @Serializable(ForeverSerializer::class)
     85     private val us: Long,
     86 ) {
     87     val ms: Long = us / 1000L
     88 
     89     companion object {
     90         internal const val FOREVER: Long = -1
     91         fun forever(): RelativeTime = fromMillis(FOREVER)
     92         fun fromMillis(ms: Long) = RelativeTime(ms / 100L)
     93     }
     94 }
     95 
     96 internal abstract class MinusOneSerializer(private val keyword: String) :
     97     JsonTransformingSerializer<Long>(Long.serializer()) {
     98 
     99     override fun transformDeserialize(element: JsonElement): JsonElement {
    100         return if (element.jsonPrimitive.contentOrNull == keyword) return JsonPrimitive(-1)
    101         else super.transformDeserialize(element)
    102     }
    103 
    104     override fun transformSerialize(element: JsonElement): JsonElement {
    105         return if (element.jsonPrimitive.longOrNull == -1L) return JsonPrimitive(keyword)
    106         else element
    107     }
    108 }
    109 
    110 internal object NeverSerializer : MinusOneSerializer("never")
    111 internal object ForeverSerializer : MinusOneSerializer("forever")