Implemented platform specific wrapper classes for BigDecimal, Date, File and UUID
This commit is contained in:
parent
2281d1758d
commit
1bef1904f9
|
@ -0,0 +1,21 @@
|
|||
package net.dankito.utils.multiplatform
|
||||
|
||||
|
||||
expect fun Collection<BigDecimal>.sum(): BigDecimal
|
||||
|
||||
|
||||
expect class BigDecimal {
|
||||
|
||||
companion object {
|
||||
val Zero: BigDecimal
|
||||
}
|
||||
|
||||
|
||||
constructor(decimal: String)
|
||||
|
||||
constructor(double: Double)
|
||||
|
||||
|
||||
fun format(pattern: String): String
|
||||
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package net.dankito.utils.multiplatform
|
||||
|
||||
|
||||
fun Date.format(format: DateFormatter): String {
|
||||
return format.format(this)
|
||||
}
|
||||
|
||||
fun Date.format(pattern: String): String {
|
||||
return this.format(DateFormatter(pattern))
|
||||
}
|
||||
|
||||
|
||||
expect class Date(millisSinceEpoch: Long) {
|
||||
|
||||
constructor()
|
||||
|
||||
|
||||
val millisSinceEpoch: Long
|
||||
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package net.dankito.utils.multiplatform
|
||||
|
||||
|
||||
enum class DateFormatStyle {
|
||||
|
||||
Short,
|
||||
|
||||
Medium,
|
||||
|
||||
Long,
|
||||
|
||||
Full
|
||||
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package net.dankito.utils.multiplatform
|
||||
|
||||
|
||||
expect class DateFormatter constructor(pattern: String) {
|
||||
|
||||
constructor(dateStyle: DateFormatStyle)
|
||||
|
||||
constructor(dateStyle: DateFormatStyle, timeStyle: DateFormatStyle)
|
||||
|
||||
|
||||
fun format(date: Date): String
|
||||
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package net.dankito.utils.multiplatform
|
||||
|
||||
|
||||
expect class File(path: String) {
|
||||
|
||||
constructor(folder: File, filename: String)
|
||||
|
||||
|
||||
// have to specify it as method as property would conflict with java.io.File's getAbsolutePath
|
||||
fun getAbsolutePath(): String
|
||||
|
||||
val filename: String
|
||||
|
||||
val fileExtension: String
|
||||
|
||||
|
||||
fun mkdirs(): Boolean
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package net.dankito.utils.multiplatform
|
||||
|
||||
|
||||
expect class UUID {
|
||||
|
||||
companion object {
|
||||
|
||||
fun random(): String
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,17 +1,18 @@
|
|||
package net.dankito.utils.multiplatform.log
|
||||
|
||||
import com.soywiz.klock.DateTime
|
||||
import net.dankito.utils.multiplatform.Date
|
||||
import net.dankito.utils.multiplatform.DateFormatter
|
||||
|
||||
|
||||
open class ConsoleLogger(name: String) : LoggerBase(name) {
|
||||
|
||||
companion object {
|
||||
private val DateFormat = com.soywiz.klock.DateFormat.invoke("HH:mm:ss.SSS")
|
||||
private val DateFormatter = DateFormatter("HH:mm:ss.SSS")
|
||||
}
|
||||
|
||||
|
||||
override fun log(level: LogLevel, message: String) {
|
||||
println("${DateTime.nowLocal().toString(DateFormat)} $level $name - $message")
|
||||
println("${DateFormatter.format(Date())} $level $name - $message")
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
package net.dankito.utils.multiplatform
|
||||
|
||||
import platform.Foundation.NSCoder
|
||||
import platform.Foundation.NSDecimalNumber
|
||||
import platform.Foundation.NSNumberFormatter
|
||||
import platform.Foundation.NSOrderedSame
|
||||
|
||||
|
||||
fun NSDecimalNumber.toBigDecimal(): BigDecimal {
|
||||
return BigDecimal(this.stringValue) // TODO: find a better way than double string conversion
|
||||
}
|
||||
|
||||
actual fun Collection<BigDecimal>.sum(): BigDecimal {
|
||||
return this.fold(NSDecimalNumber.zero) { acc, e -> acc.decimalNumberByAdding(e) }.toBigDecimal()
|
||||
}
|
||||
|
||||
|
||||
actual class BigDecimal actual constructor(decimal: String) : NSDecimalNumber(NSCoder()) {
|
||||
|
||||
actual companion object {
|
||||
actual val Zero = BigDecimal("0") // TODO: is this correct?
|
||||
}
|
||||
|
||||
|
||||
actual constructor(double: Double) : this(NSDecimalNumber(double).stringValue)
|
||||
|
||||
|
||||
init {
|
||||
super.decimalNumberByAdding(NSDecimalNumber(decimal))
|
||||
}
|
||||
|
||||
|
||||
actual fun format(pattern: String): String {
|
||||
val formatter = NSNumberFormatter()
|
||||
|
||||
formatter.positiveFormat = pattern
|
||||
formatter.negativeFormat = pattern
|
||||
|
||||
return formatter.stringFromNumber(this) ?: ""
|
||||
}
|
||||
|
||||
|
||||
override fun isEqual(`object`: Any?): Boolean {
|
||||
if (`object` is BigDecimal) {
|
||||
return this.compare(`object`) == NSOrderedSame
|
||||
}
|
||||
|
||||
return super.equals(`object`)
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package net.dankito.utils.multiplatform
|
||||
|
||||
import platform.Foundation.*
|
||||
|
||||
|
||||
fun NSTimeInterval.toMillis(): Long {
|
||||
return this.toLong() * 1000
|
||||
}
|
||||
|
||||
|
||||
actual class Date actual constructor(millisSinceEpoch: Long)
|
||||
: NSDate(timeIntervalSinceReferenceDate = ((millisSinceEpoch - DiffBetweenEpochTimeAndReferenceDate) / 1000).toDouble()) { // TODO: does this work?
|
||||
|
||||
companion object {
|
||||
val DiffBetweenEpochTimeAndReferenceDate = (NSDate.timeIntervalSinceReferenceDate - NSTimeIntervalSince1970).toMillis()
|
||||
}
|
||||
|
||||
|
||||
actual constructor() : this(NSDate().timeIntervalSince1970.toMillis())
|
||||
|
||||
|
||||
actual val millisSinceEpoch: Long
|
||||
get() = timeIntervalSince1970.toMillis()
|
||||
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package net.dankito.utils.multiplatform
|
||||
|
||||
import platform.Foundation.*
|
||||
|
||||
|
||||
fun DateFormatStyle.convert(): ULong {
|
||||
return when (this) {
|
||||
DateFormatStyle.Short -> NSDateFormatterShortStyle
|
||||
DateFormatStyle.Medium -> NSDateFormatterMediumStyle
|
||||
DateFormatStyle.Long -> NSDateFormatterLongStyle
|
||||
DateFormatStyle.Full -> NSDateFormatterFullStyle
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
actual class DateFormatter actual constructor(val pattern: String): NSDateFormatter() {
|
||||
|
||||
actual constructor(dateStyle: DateFormatStyle) : this(NSDateFormatter().apply {
|
||||
this.dateStyle = dateStyle.convert()
|
||||
}.dateFormat) // TODO: does this work?
|
||||
|
||||
actual constructor(dateStyle: DateFormatStyle, timeStyle: DateFormatStyle) : this(NSDateFormatter().apply {
|
||||
this.dateStyle = dateStyle.convert()
|
||||
this.timeStyle = timeStyle.convert()
|
||||
}.dateFormat) // TODO: does this work?
|
||||
|
||||
|
||||
init {
|
||||
this.dateFormat = pattern
|
||||
|
||||
this.timeZone = NSTimeZone.localTimeZone // TODO: needed?
|
||||
}
|
||||
|
||||
|
||||
actual fun format(date: Date): String {
|
||||
return stringFromDate(date)
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package net.dankito.utils.multiplatform
|
||||
|
||||
import platform.Foundation.NSFileManager
|
||||
import platform.Foundation.NSURL
|
||||
import platform.Foundation.lastPathComponent
|
||||
|
||||
|
||||
actual class File actual constructor(path: String) : NSURL(fileURLWithPath = path) {
|
||||
|
||||
actual constructor(folder: File, filename: String)
|
||||
: this(NSURL(string = filename, relativeToURL = folder).absoluteString ?: "") // TODO: or use 'fileURLWithPath'?
|
||||
|
||||
|
||||
actual fun getAbsolutePath(): String {
|
||||
return absoluteString ?: absoluteURL?.absoluteString ?: path ?: ""
|
||||
}
|
||||
|
||||
actual val filename: String
|
||||
get() = lastPathComponent ?: ""
|
||||
|
||||
actual val fileExtension: String
|
||||
get() = filename.substringAfterLast('.', "")
|
||||
|
||||
|
||||
actual fun mkdirs(): Boolean {
|
||||
return NSFileManager.defaultManager.createDirectoryAtURL(this, true, null, null)
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package net.dankito.utils.multiplatform
|
||||
|
||||
import platform.Foundation.NSUUID
|
||||
|
||||
|
||||
actual class UUID {
|
||||
|
||||
actual companion object {
|
||||
|
||||
actual fun random(): String {
|
||||
return NSUUID().UUIDString
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
package net.dankito.utils.multiplatform
|
||||
|
||||
|
||||
fun java.math.BigDecimal.toBigDecimal(): BigDecimal {
|
||||
return BigDecimal(this.toPlainString()) // TODO: find a better way than double string conversion
|
||||
}
|
||||
|
||||
actual fun Collection<BigDecimal>.sum(): BigDecimal {
|
||||
return this.fold(java.math.BigDecimal.ZERO) { acc, e -> (acc + e) }.toBigDecimal()
|
||||
}
|
||||
|
||||
|
||||
actual class BigDecimal actual constructor(decimal: String) : java.math.BigDecimal(decimal) {
|
||||
|
||||
actual companion object {
|
||||
actual val Zero =
|
||||
BigDecimal("0") // TODO: is this correct?
|
||||
}
|
||||
|
||||
|
||||
internal constructor() : this("0") // for object deserializers
|
||||
|
||||
actual constructor(double: Double) : this(java.math.BigDecimal.valueOf(double).toPlainString()) // for object deserializers
|
||||
|
||||
|
||||
actual fun format(pattern: String): String {
|
||||
return String.format(pattern, this)
|
||||
}
|
||||
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other is BigDecimal) {
|
||||
return this.compareTo(other) == 0
|
||||
}
|
||||
|
||||
return super.equals(other)
|
||||
}
|
||||
|
||||
|
||||
/* TODO: where are these methods coming from? */
|
||||
|
||||
override fun toByte(): Byte {
|
||||
return 0 // will never be called; where is this method coming from?
|
||||
}
|
||||
|
||||
override fun toChar(): Char {
|
||||
return 0.toChar() // will never be called; where is this method coming from?
|
||||
}
|
||||
|
||||
override fun toShort(): Short {
|
||||
return 0 // will never be called; where is this method coming from?
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package net.dankito.utils.multiplatform
|
||||
|
||||
|
||||
actual class Date actual constructor(millisSinceEpoch: Long) : java.util.Date(millisSinceEpoch) {
|
||||
|
||||
actual constructor() : this(System.currentTimeMillis())
|
||||
|
||||
|
||||
actual val millisSinceEpoch: Long
|
||||
get() = time
|
||||
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
package net.dankito.utils.multiplatform
|
||||
|
||||
import java.text.DateFormat
|
||||
import java.text.SimpleDateFormat
|
||||
|
||||
|
||||
fun DateFormatStyle.convert(): Int {
|
||||
return when (this) {
|
||||
DateFormatStyle.Short -> DateFormat.SHORT
|
||||
DateFormatStyle.Medium -> DateFormat.MEDIUM
|
||||
DateFormatStyle.Long -> DateFormat.LONG
|
||||
DateFormatStyle.Full -> DateFormat.FULL
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
actual class DateFormatter actual constructor(val pattern: String): SimpleDateFormat(pattern) {
|
||||
|
||||
actual constructor(dateStyle: DateFormatStyle)
|
||||
: this((DateFormat.getDateInstance(dateStyle.convert()) as? SimpleDateFormat)?.toPattern() ?: "")
|
||||
|
||||
actual constructor(dateStyle: DateFormatStyle, timeStyle: DateFormatStyle)
|
||||
: this((DateFormat.getDateTimeInstance(dateStyle.convert(), timeStyle.convert()) as? SimpleDateFormat)?.toPattern() ?: "")
|
||||
|
||||
|
||||
actual fun format(date: Date): String {
|
||||
return super.format(date)
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
package net.dankito.utils.multiplatform
|
||||
|
||||
|
||||
fun java.util.Date.toDate(): Date {
|
||||
return Date(this.time)
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
package net.dankito.utils.multiplatform
|
||||
|
||||
import java.io.File
|
||||
|
||||
|
||||
fun File.toFile(): net.dankito.utils.multiplatform.File {
|
||||
return net.dankito.utils.multiplatform.File(this.absolutePath)
|
||||
}
|
||||
|
||||
|
||||
actual class File actual constructor(path: String) : File(path) {
|
||||
|
||||
actual constructor(folder: net.dankito.utils.multiplatform.File, filename: String)
|
||||
: this(File(folder, filename).absolutePath)
|
||||
|
||||
|
||||
internal constructor() : this("") // for object deserializers
|
||||
|
||||
|
||||
actual override fun getAbsolutePath(): String {
|
||||
return super.getAbsolutePath()
|
||||
}
|
||||
|
||||
actual val filename: String
|
||||
get() = super.getName()
|
||||
|
||||
actual val fileExtension: String
|
||||
get() = this.extension
|
||||
|
||||
|
||||
actual override fun mkdirs(): Boolean {
|
||||
return super.mkdirs()
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package net.dankito.utils.multiplatform
|
||||
|
||||
import java.util.UUID
|
||||
|
||||
|
||||
actual class UUID {
|
||||
|
||||
actual companion object {
|
||||
|
||||
actual fun random(): String {
|
||||
return UUID.randomUUID().toString()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package net.dankito.utils.multiplatform.log
|
||||
|
||||
|
||||
actual class DefaultLoggerFactory {
|
||||
|
||||
actual fun createDefaultLoggerFactory(): ILoggerFactory {
|
||||
if (isClassAvailable("org.slf4j.Logger")) {
|
||||
return Slf4jLoggerFactory()
|
||||
}
|
||||
|
||||
return LogToConsoleLoggerFactory()
|
||||
}
|
||||
|
||||
private fun isClassAvailable(qualifiedClassName: String): Boolean {
|
||||
try {
|
||||
Class.forName(qualifiedClassName)
|
||||
|
||||
return true
|
||||
} catch (ignored: Exception) { }
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue