0.2.0 完善功能
This commit is contained in:
10
src/gaea/build.gradle
Normal file
10
src/gaea/build.gradle
Normal file
@@ -0,0 +1,10 @@
|
||||
publishing {
|
||||
publications {
|
||||
mavenJava(MavenPublication) {
|
||||
group 'com.synebula'
|
||||
artifactId 'gaea.data'
|
||||
version project.version
|
||||
from components.java
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.synebula.gaea.data
|
||||
|
||||
/**
|
||||
* 对象转换器,支持对象之间的转换。
|
||||
*
|
||||
* @author alex
|
||||
* @version 0.1
|
||||
* @since 2018 18-2-2
|
||||
*/
|
||||
interface IObjectConverter {
|
||||
|
||||
/**
|
||||
* 转换源对象到目标对象。
|
||||
*
|
||||
* @param src 源对象。
|
||||
* @param dest 目标对象。
|
||||
* @param <T> 目标对象类型。
|
||||
* @return 目标对象
|
||||
*/
|
||||
fun <T> convert(src: Any, dest: Class<T>): T
|
||||
}
|
||||
49
src/gaea/src/main/kotlin/com/synebula/gaea/data/cache/CacheEntity.kt
vendored
Normal file
49
src/gaea/src/main/kotlin/com/synebula/gaea/data/cache/CacheEntity.kt
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
package com.synebula.gaea.data.cache
|
||||
|
||||
import java.util.Date
|
||||
|
||||
/**
|
||||
*
|
||||
* @author alex
|
||||
* @version 0.0.1
|
||||
* @since 2016年9月29日 下午1:38:58
|
||||
*/
|
||||
data class CacheEntity(var key: String, var value: Any) {
|
||||
/**
|
||||
* 超时时间,单位s
|
||||
*/
|
||||
var overtime: Int = 60
|
||||
private set
|
||||
|
||||
/**
|
||||
* true代表绝对过期时间,false代表滑动过期。\n
|
||||
* 滑动过期是指每次操作都会重新刷新缓存的超时时间。
|
||||
*/
|
||||
var isAbsolute: Boolean = true
|
||||
private set
|
||||
var timestamp: Long = Date().time
|
||||
private set
|
||||
|
||||
constructor(key: String, value: Any, overtime: Int) : this(key, value) {
|
||||
this.overtime = overtime
|
||||
}
|
||||
|
||||
constructor(key: String, value: Any, overtime: Int, isAbsolute: Boolean) : this(key, value, overtime) {
|
||||
this.isAbsolute = isAbsolute
|
||||
}
|
||||
|
||||
/**
|
||||
* 缓存对象是否过期
|
||||
*/
|
||||
fun isExpired(): Boolean =
|
||||
Date().time > this.timestamp + this.overtime * 1000
|
||||
|
||||
|
||||
/**
|
||||
* 刷新缓存时间,仅在滑动过期下有效。
|
||||
*/
|
||||
fun refresh() {
|
||||
if (!isAbsolute)
|
||||
this.timestamp = Date().time
|
||||
}
|
||||
}
|
||||
14
src/gaea/src/main/kotlin/com/synebula/gaea/data/cache/ICache.kt
vendored
Normal file
14
src/gaea/src/main/kotlin/com/synebula/gaea/data/cache/ICache.kt
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
package com.synebula.gaea.data.cache
|
||||
|
||||
/**
|
||||
* 缓存接口。
|
||||
*
|
||||
* @author alex
|
||||
* @version 0.0.1
|
||||
* @since 2016年8月15日 下午4:53:19
|
||||
*/
|
||||
interface ICache {
|
||||
fun add(key: String, value: CacheEntity)
|
||||
|
||||
operator fun get(key: String): CacheEntity
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.synebula.gaea.data.code
|
||||
|
||||
/**
|
||||
* 组合编号,根据模板组合生成编号。
|
||||
*
|
||||
* @author alex
|
||||
* @version 0.0.1
|
||||
* @since 2016年10月24日 下午2:53:50
|
||||
*/
|
||||
class CompositeCode(val generators: List<ICodeGenerator<*>>?) : ICodeGenerator<String> {
|
||||
|
||||
/*
|
||||
* Method
|
||||
*/
|
||||
|
||||
override fun generate(): String {
|
||||
if (this.generators == null || generators.size == 0)
|
||||
return ""
|
||||
val buffer = StringBuffer()
|
||||
for (generator in generators) {
|
||||
buffer.append(generator.generate())
|
||||
}
|
||||
return buffer.toString()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.synebula.gaea.data.code
|
||||
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
|
||||
/**
|
||||
* @author alex
|
||||
* @version 0.0.1
|
||||
* @since 2016年10月24日 下午3:42:47
|
||||
* @param pattern 时间格式化模式。不需要定制可以选择默认构造方法:"yyyyMMdd"。
|
||||
* 参数:年=y,月=M,日=d,时=H,分=m,秒=s,毫秒=S。位数最好使用默认最大长度。
|
||||
*/
|
||||
class DateCode(pattern: String = "yyyyMMdd") : ICodeGenerator<Long> {
|
||||
var formator = SimpleDateFormat()
|
||||
|
||||
init {
|
||||
formator.applyPattern(pattern)
|
||||
}
|
||||
|
||||
override fun generate(): Long {
|
||||
return java.lang.Long.parseLong(formator.format(Date()))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package com.synebula.gaea.data.code
|
||||
|
||||
import java.util.Random
|
||||
|
||||
/**
|
||||
* 固定长度随机编号生成。
|
||||
* @author alex
|
||||
* @version 0.0.1
|
||||
* @since 2016年10月24日 上午10:58:05
|
||||
*/
|
||||
class FixedRandomCode(
|
||||
//生成的随机编号长度。
|
||||
var length: Int
|
||||
) : ICodeGenerator<String> {
|
||||
|
||||
/**
|
||||
* 随机数生成器。
|
||||
*/
|
||||
private val random = Random()
|
||||
|
||||
/**
|
||||
* 计算最大长度,不能超过9
|
||||
*/
|
||||
internal var calcMaxLength = 10
|
||||
|
||||
override fun generate(): String {
|
||||
/*
|
||||
* 如果最大长度超过特定长度(默认10),则分多次随机数计算,然后拼接。
|
||||
* 最后一次的数量是对计算长度对特定长度的取模。如13前次要循环计算1次,最后计算3位随机数。
|
||||
*/
|
||||
val buffer = StringBuffer()
|
||||
var format = String.format("%s%d%dd", "%", 0, calcMaxLength)
|
||||
val count = this.length / calcMaxLength
|
||||
for (i in 0 until count) {
|
||||
buffer.append(String.format(format, (random.nextDouble() * Math.pow(10.0, calcMaxLength.toDouble())).toInt()))
|
||||
}
|
||||
val last = this.length % calcMaxLength
|
||||
if (last != 0) {
|
||||
format = String.format("%s%d%dd", "%", 0, last)
|
||||
buffer.append(String.format(format, (random.nextDouble() * Math.pow(10.0, last.toDouble())).toInt()))
|
||||
}
|
||||
return buffer.toString()
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package com.synebula.gaea.data.code
|
||||
|
||||
/**
|
||||
* 序列编号,自增的编号。
|
||||
*
|
||||
* @author alex
|
||||
* @version 0.0.1
|
||||
* @since 2016年10月24日 下午3:17:36
|
||||
*/
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param length 流水号固定长度,不足前面默认补零,值小于零则表示为不定长。
|
||||
* @param seed 种子,初始值。
|
||||
* @param step 步进,每次增长数量。
|
||||
*/
|
||||
class FixedSerialCode(
|
||||
/**
|
||||
* code长度,不足前面补零。
|
||||
*/
|
||||
var length: Int = 0,
|
||||
/**
|
||||
* 种子,初始值。
|
||||
*/
|
||||
var seed: Int = 1,
|
||||
/**
|
||||
* 步进,每次增长数量。
|
||||
*/
|
||||
var step: Int = 1
|
||||
) : ICodeGenerator<String> {
|
||||
|
||||
|
||||
/*
|
||||
* Method
|
||||
*/
|
||||
|
||||
@Synchronized
|
||||
override fun generate(): String {
|
||||
val value = this.seed
|
||||
this.seed += this.step
|
||||
var format = "%d"
|
||||
if (this.length > 0) {
|
||||
format = String.format("%s%d%dd", "%", 0, this.length)
|
||||
}
|
||||
return String.format(format, value)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.synebula.gaea.data.code
|
||||
|
||||
import java.util.UUID
|
||||
|
||||
/**
|
||||
* 全球唯一编号生成。
|
||||
*
|
||||
* @author alex
|
||||
* @version 0.0.1
|
||||
* @since 2016年10月24日 下午2:46:09
|
||||
*/
|
||||
class GUIDCode : ICodeGenerator<String> {
|
||||
|
||||
override fun generate(): String {
|
||||
return UUID.randomUUID().toString().replace("-".toRegex(), "")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.synebula.gaea.data.code
|
||||
|
||||
/**
|
||||
* 继承本接口的类,都能实现编号生成工作。
|
||||
*
|
||||
* @author alex
|
||||
* @version 0.0.1
|
||||
* @since 2016年10月24日 上午10:41:03
|
||||
*/
|
||||
interface ICodeGenerator<T> {
|
||||
/**
|
||||
* 生成编号。
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
fun generate(): T
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
package com.synebula.gaea.data.code
|
||||
|
||||
/**
|
||||
* class SnowflakeCode
|
||||
*
|
||||
* @author alex
|
||||
* @version 0.1
|
||||
* @since 2018 18-2-1
|
||||
*
|
||||
*
|
||||
* Twitter_Snowflake<br></br>
|
||||
* SnowFlake的结构如下(每部分用-分开):<br></br>
|
||||
* 0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000 <br></br>
|
||||
* 1位标识,由于long基本类型在Java中是带符号的,最高位是符号位,正数是0,负数是1,所以id一般是正数,最高位是0<br></br>
|
||||
* 41位时间截(毫秒级),注意,41位时间截不是存储当前时间的时间截,而是存储时间截的差值(当前时间截 - 开始时间截)<br></br>
|
||||
* 得到的值),这里的的开始时间截,一般是我们的id生成器开始使用的时间,由我们程序来指定的(如下下面程序Snowflake类的twepoch属性)。<br></br>
|
||||
* 41位的时间截,可以使用69年,年T = (1L << 41) / (1000L * 60 * 60 * 24 * 365) = 69 <br></br>
|
||||
* 10位的数据机器位,可以部署在1024个节点,包括5位datacenter和5位worker <br></br>
|
||||
* 12位序列,毫秒内的计数,12位的计数顺序号支持每个节点每毫秒(同一机器,同一时间截)产生4096个ID序号<br></br>
|
||||
* 加起来刚好64位,为一个Long型。<br></br>
|
||||
* SnowFlake的优点是,整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞(由数据中心ID和机器ID作区分),并且效率较高,经测试,SnowFlake每秒能够产生26万ID左右。
|
||||
*/
|
||||
open class SnowflakeCode(
|
||||
/**
|
||||
* 数据中心ID(0~31)
|
||||
*/
|
||||
private val datacenter: Long,
|
||||
/**
|
||||
* 工作机器ID(0~31)
|
||||
*/
|
||||
private val worker: Long
|
||||
) : ICodeGenerator<Long> {
|
||||
|
||||
// ==============================Fields===========================================
|
||||
/**
|
||||
* 开始时间截 (2018-01-01)
|
||||
*/
|
||||
private val twepoch = 1514736000000L
|
||||
|
||||
/**
|
||||
* 机器id所占的位数
|
||||
*/
|
||||
private val workerBits = 5
|
||||
|
||||
/**
|
||||
* 数据标识id所占的位数
|
||||
*/
|
||||
private val datacenterBits = 5
|
||||
|
||||
/**
|
||||
* 支持的最大机器id,结果是31 (这个移位算法可以很快的计算出几位二进制数所能表示的最大十进制数)
|
||||
*/
|
||||
private val maxWorker = -1L xor (-1L shl workerBits)
|
||||
|
||||
/**
|
||||
* 支持的最大数据标识id,结果是31
|
||||
*/
|
||||
private val maxDatacenter = -1L xor (-1L shl datacenterBits)
|
||||
|
||||
/**
|
||||
* 序列在id中占的位数
|
||||
*/
|
||||
private val sequenceBits = 12
|
||||
|
||||
/**
|
||||
* 机器ID向左移12位
|
||||
*/
|
||||
private val workerShift = sequenceBits
|
||||
|
||||
/**
|
||||
* 数据标识id向左移17位(12+5)
|
||||
*/
|
||||
private val datacenterShift = sequenceBits + workerBits
|
||||
|
||||
/**
|
||||
* 时间截向左移22位(5+5+12)
|
||||
*/
|
||||
private val timestampLeftShift = sequenceBits + workerBits + datacenterBits
|
||||
|
||||
/**
|
||||
* 生成序列的掩码,这里为4095 (0b111111111111=0xfff=4095)
|
||||
*/
|
||||
private val sequenceMask = -1L xor (-1L shl sequenceBits)
|
||||
|
||||
/**
|
||||
* 毫秒内序列(0~4095)
|
||||
*/
|
||||
private var sequence = 0L
|
||||
|
||||
/**
|
||||
* 上次生成ID的时间截
|
||||
*/
|
||||
private var lastTimestamp = -1L
|
||||
|
||||
/**
|
||||
* 返回以毫秒为单位的当前时间
|
||||
*
|
||||
* @return 当前时间(毫秒)
|
||||
*/
|
||||
protected val timestamp: Long
|
||||
get() = System.currentTimeMillis()
|
||||
|
||||
init {
|
||||
if (worker > maxWorker || worker < 0) {
|
||||
throw IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorker))
|
||||
}
|
||||
if (datacenter > maxDatacenter || datacenter < 0) {
|
||||
throw IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenter))
|
||||
}
|
||||
}
|
||||
|
||||
// ==============================Methods==========================================
|
||||
|
||||
/**
|
||||
* 获得下一个ID (该方法是线程安全的)
|
||||
*
|
||||
* @return SnowflakeId
|
||||
*/
|
||||
@Synchronized
|
||||
override fun generate(): Long {
|
||||
var current = timestamp
|
||||
|
||||
//如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退过这个时候应当抛出异常
|
||||
if (current < lastTimestamp) {
|
||||
throw RuntimeException(
|
||||
String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - current))
|
||||
}
|
||||
|
||||
//如果是同一时间生成的,则进行毫秒内序列
|
||||
if (lastTimestamp == current) {
|
||||
sequence = sequence + 1 and sequenceMask
|
||||
//毫秒内序列溢出
|
||||
if (sequence == 0L) {
|
||||
//阻塞到下一个毫秒,获得新的时间戳
|
||||
current = getNextTimestamp(lastTimestamp)
|
||||
}
|
||||
} else {
|
||||
sequence = 0L
|
||||
}//时间戳改变,毫秒内序列重置
|
||||
|
||||
//上次生成ID的时间截
|
||||
lastTimestamp = current
|
||||
|
||||
//移位并通过或运算拼到一起组成64位的ID
|
||||
return (current - twepoch shl timestampLeftShift
|
||||
or (datacenter shl datacenterShift)
|
||||
or (worker shl workerShift)
|
||||
or sequence)
|
||||
}
|
||||
|
||||
/**
|
||||
* 阻塞到下一个毫秒,直到获得新的时间戳
|
||||
*
|
||||
* @param lastTimestamp 上次生成ID的时间截
|
||||
* @return 当前时间戳
|
||||
*/
|
||||
protected fun getNextTimestamp(lastTimestamp: Long): Long {
|
||||
var current = timestamp
|
||||
while (current <= lastTimestamp) {
|
||||
current = timestamp
|
||||
}
|
||||
return current
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.synebula.gaea.data.code
|
||||
|
||||
/**
|
||||
* 默认值编号,返回默认值。
|
||||
*
|
||||
* @author alex
|
||||
* @version 0.0.1
|
||||
* @since 2016年10月24日 下午4:07:10
|
||||
*/
|
||||
class ValueCode(var value: String) : ICodeGenerator<String> {
|
||||
|
||||
/*
|
||||
* Method
|
||||
*/
|
||||
override fun generate(): String {
|
||||
return this.value
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
package com.synebula.gaea.data.date
|
||||
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* 校准时间。
|
||||
* 根据标准时间和间隔时间,获取就近的校准时间。
|
||||
* 如:2019-1-1 10:10:25, 根据标准时间2019-1-1 10:10:00按40s的间隔会校准为2019-1-1 10:10:40.
|
||||
*/
|
||||
class AlignTime {
|
||||
/**
|
||||
* 间隔时间,默认为1s
|
||||
*/
|
||||
var intervalSeconds = 1
|
||||
|
||||
/**
|
||||
* 标准时间。默认为2018-1-1 0:0:0
|
||||
*/
|
||||
var baseTime = DateTime(2018, 0, 1, 0, 0, 0)
|
||||
|
||||
constructor(intervalSeconds: Int) {
|
||||
this.intervalSeconds = intervalSeconds
|
||||
}
|
||||
|
||||
constructor(baseTime: DateTime) {
|
||||
this.baseTime = baseTime
|
||||
}
|
||||
|
||||
constructor(baseTime: DateTime, intervalSeconds: Int) {
|
||||
this.baseTime = baseTime
|
||||
this.intervalSeconds = intervalSeconds
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取就近的校准时间。
|
||||
* 如果时间刚好是正点时间,则输出该时间。如果不是正点时间则输出大于该时间的校准正点时间。
|
||||
*/
|
||||
fun ceilingTime(): DateTime {
|
||||
return ceilingTime(DateTime(Date()))
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取就近的校准时间。
|
||||
* 如果时间刚好是正点时间,则输出该时间。如果不是正点时间则输出大于该时间的校准正点时间。
|
||||
*/
|
||||
fun ceilingTime(lastTime: DateTime): DateTime {
|
||||
return this.ceilingTime(lastTime, this.intervalSeconds)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取就近的校准时间。
|
||||
* 如果时间刚好是正点时间,则输出该时间。如果不是正点时间则输出大于该时间的校准正点时间。
|
||||
*/
|
||||
fun ceilingTime(intervalSeconds: Int): DateTime {
|
||||
return this.ceilingTime(this.baseTime, intervalSeconds)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取就近的校准时间。
|
||||
* 如果时间刚好是正点时间,则输出该时间。如果不是正点时间则输出大于该时间的校准正点时间。
|
||||
*/
|
||||
fun ceilingTime(lastTime: DateTime, intervalSeconds: Int): DateTime {
|
||||
val span = lastTime - this.baseTime
|
||||
val count = Math.ceil(span.totalSeconds / intervalSeconds).toInt()
|
||||
val newTime = DateTime(this.baseTime.date)
|
||||
newTime.addSeconds(count * intervalSeconds * 1L)
|
||||
return newTime
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取就近的校准时间。
|
||||
* 如果时间刚好是正点时间,则输出该时间。如果不是正点时间则输出小于该时间的校准正点时间。
|
||||
*/
|
||||
fun floorTime(): DateTime {
|
||||
return floorTime(DateTime(Date()))
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取就近的校准时间。
|
||||
* 如果时间刚好是正点时间,则输出该时间。如果不是正点时间则输出小于该时间的校准正点时间。
|
||||
*/
|
||||
fun floorTime(lastTime: DateTime): DateTime {
|
||||
return this.floorTime(lastTime, this.intervalSeconds)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取就近的校准时间。
|
||||
* 如果时间刚好是正点时间,则输出该时间。如果不是正点时间则输出小于该时间的校准正点时间。
|
||||
*/
|
||||
fun floorTime(intervalSeconds: Int): DateTime {
|
||||
return this.floorTime(this.baseTime, intervalSeconds)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取就近的校准时间。
|
||||
* 如果时间刚好是正点时间,则输出该时间。如果不是正点时间则输出小于该时间的校准正点时间。
|
||||
*/
|
||||
fun floorTime(lastTime: DateTime, intervalSeconds: Int): DateTime {
|
||||
val span = lastTime - this.baseTime
|
||||
val count = Math.floor(span.totalSeconds / intervalSeconds).toInt()
|
||||
val newTime = DateTime(this.baseTime.date)
|
||||
newTime.addSeconds(count * intervalSeconds * 1L)
|
||||
return newTime
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.synebula.gaea.data.date
|
||||
|
||||
import java.util.*
|
||||
|
||||
|
||||
/**
|
||||
* 日期相减
|
||||
*/
|
||||
operator fun Date.minus(other: Date): TimeSpan {
|
||||
return TimeSpan(this.time - other.time)
|
||||
}
|
||||
197
src/gaea/src/main/kotlin/com/synebula/gaea/data/date/DateTime.kt
Normal file
197
src/gaea/src/main/kotlin/com/synebula/gaea/data/date/DateTime.kt
Normal file
@@ -0,0 +1,197 @@
|
||||
package com.synebula.gaea.data.date
|
||||
|
||||
import com.synebula.gaea.data.type.TimeUnit
|
||||
import java.text.ParseException
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* 时间格式,方便用于获取Date格式的多种形式
|
||||
*/
|
||||
class DateTime : Comparable<DateTime> {
|
||||
|
||||
// 内部存储日历格式方便操作
|
||||
/**
|
||||
* 返回内部日历格式类型。
|
||||
* @return 日历格式类型。
|
||||
*/
|
||||
private var calendar = Calendar.getInstance()!!
|
||||
|
||||
/**
|
||||
* 当前时间的总毫秒数。
|
||||
*/
|
||||
private val milliseconds: Long
|
||||
get() = this.calendar.timeInMillis
|
||||
|
||||
/**
|
||||
* 列出时间的级别数组
|
||||
*/
|
||||
private val calendarLevel = intArrayOf(Calendar.MILLISECOND, Calendar.SECOND, Calendar.MINUTE, Calendar.HOUR_OF_DAY, Calendar.DAY_OF_MONTH, Calendar.MONTH, Calendar.YEAR)
|
||||
|
||||
val date: Date
|
||||
get() = calendar.time
|
||||
|
||||
/**
|
||||
* 获取去除了时间部分的日期类型。
|
||||
*/
|
||||
val dateNoTime: Date
|
||||
get() {
|
||||
val instance = calendar.clone() as Calendar
|
||||
instance.set(Calendar.HOUR_OF_DAY, 0)
|
||||
instance.set(Calendar.MINUTE, 0)
|
||||
instance.set(Calendar.SECOND, 0)
|
||||
instance.set(Calendar.MILLISECOND, 0)
|
||||
return instance.time
|
||||
}
|
||||
|
||||
var year: Int
|
||||
get() = calendar.get(Calendar.YEAR)
|
||||
set(value) = calendar.set(Calendar.YEAR, value)
|
||||
|
||||
var month: Int
|
||||
get() = calendar.get(Calendar.MONTH)
|
||||
set(value) = calendar.set(Calendar.MONTH, value)
|
||||
|
||||
var day: Int
|
||||
get() = calendar.get(Calendar.DAY_OF_MONTH)
|
||||
set(value) = calendar.set(Calendar.DAY_OF_MONTH, value)
|
||||
|
||||
val time: Time
|
||||
get() = Time(calendar.time)
|
||||
|
||||
val firstDay: DateTime
|
||||
get() {
|
||||
val instance = calendar.clone() as Calendar
|
||||
instance.set(Calendar.DAY_OF_MONTH, 1)
|
||||
return DateTime(instance)
|
||||
}
|
||||
|
||||
val lastDay: DateTime
|
||||
get() {
|
||||
val instance = calendar.clone() as Calendar
|
||||
instance.set(Calendar.DAY_OF_MONTH, instance.getActualMaximum(Calendar.DAY_OF_MONTH))
|
||||
return DateTime(instance)
|
||||
}
|
||||
|
||||
constructor()
|
||||
|
||||
/**
|
||||
* 从Date格式转化
|
||||
*/
|
||||
constructor(date: Date) {
|
||||
this.calendar.time = date
|
||||
this.calendar.set(Calendar.MILLISECOND, 0)
|
||||
}
|
||||
|
||||
/**
|
||||
* 从Calendar格式转化
|
||||
*/
|
||||
constructor(calendar: Calendar) {
|
||||
this.calendar = calendar
|
||||
this.calendar.set(Calendar.MILLISECOND, 0)
|
||||
}
|
||||
|
||||
/**
|
||||
* 从Date格式转化
|
||||
*/
|
||||
constructor(date: String, format: String) {
|
||||
val formatter = SimpleDateFormat(format)
|
||||
try {
|
||||
val value = formatter.parse(date)
|
||||
this.calendar.time = value
|
||||
this.calendar.set(Calendar.MILLISECOND, 0)
|
||||
} catch (e: ParseException) {
|
||||
throw RuntimeException("date string can't format to date", e)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从Date格式转化。需要注意的是月0代表是一月,以此类推。
|
||||
*/
|
||||
constructor(year: Int, month: Int, day: Int = 0, hour: Int = 0, minute: Int = 0, second: Int = 0) {
|
||||
this.calendar.set(year, month, day, hour, minute, second)
|
||||
this.calendar.set(Calendar.MILLISECOND, 0)
|
||||
}
|
||||
|
||||
/**
|
||||
* 输入字符串。
|
||||
*/
|
||||
override fun toString(): String {
|
||||
return calendar.time.toString()
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化输出字符串。
|
||||
*/
|
||||
fun toString(format: String): String {
|
||||
val formatter = SimpleDateFormat(format)
|
||||
return formatter.format(calendar.time)
|
||||
}
|
||||
|
||||
/**
|
||||
* 比较两个时间的大小。
|
||||
* -1当前时间早于目标时间,0两个时间相等,1当前时间晚于目标时间。
|
||||
* @param other 目标时间。
|
||||
* @return -1当前时间早于目标时间,0两个时间相等,1当前时间晚于目标时间。
|
||||
*/
|
||||
override fun compareTo(other: DateTime): Int {
|
||||
return this.calendar.compareTo(other.calendar)
|
||||
}
|
||||
|
||||
/**
|
||||
* 比较两个时间的大小, 考虑时间级别的敏感程度。如 了level选择秒,则忽略毫秒值。
|
||||
* -1当前时间早于目标时间,0两个时间相等,1当前时间晚于目标时间。
|
||||
* @param o 目标时间。
|
||||
* @param level 比较时间的最小级别。
|
||||
* @return -1当前时间早于目标时间,0两个时间相等,1当前时间晚于目标时间。
|
||||
*/
|
||||
fun compareTo(o: DateTime, level: TimeUnit): Int {
|
||||
val first = this.calendar.clone() as Calendar
|
||||
val second = o.calendar.clone() as Calendar
|
||||
for (i in 0 until level.ordinal) {
|
||||
first.set(calendarLevel[i], 0)
|
||||
second.set(calendarLevel[i], 0)
|
||||
}
|
||||
return first.compareTo(second)
|
||||
}
|
||||
|
||||
/**
|
||||
* 比较当前时间是否在目标时间范围内。
|
||||
* @param start 目标开始时间。
|
||||
* @param end 目标结束时间。
|
||||
* @return 是否。
|
||||
*/
|
||||
fun between(start: DateTime, end: DateTime): Boolean {
|
||||
return this in start..end
|
||||
}
|
||||
|
||||
/**
|
||||
* 比较当前时间是否在目标时间范围内。
|
||||
* @param start 目标开始时间。
|
||||
* @param end 目标结束时间。
|
||||
* @param level 比较时间的最小级别。
|
||||
* @return 是否。
|
||||
*/
|
||||
fun between(start: DateTime, end: DateTime, level: TimeUnit): Boolean {
|
||||
return this.compareTo(start, level) >= 0 && this.compareTo(end, level) <= 0
|
||||
}
|
||||
|
||||
/**
|
||||
* 增加秒
|
||||
*/
|
||||
fun addSeconds(seconds: Long) {
|
||||
if (seconds <= Int.MAX_VALUE)
|
||||
this.calendar.add(Calendar.SECOND, seconds.toInt())
|
||||
else {
|
||||
val span = TimeSpan(seconds * 1000)
|
||||
this.calendar.add(Calendar.DAY_OF_MONTH, span.day)
|
||||
this.calendar.add(Calendar.HOUR_OF_DAY, span.hour)
|
||||
this.calendar.add(Calendar.MINUTE, span.minute)
|
||||
this.calendar.add(Calendar.SECOND, span.second)
|
||||
}
|
||||
}
|
||||
|
||||
operator fun minus(other: DateTime): TimeSpan {
|
||||
return TimeSpan(this.milliseconds - other.milliseconds)
|
||||
}
|
||||
}
|
||||
94
src/gaea/src/main/kotlin/com/synebula/gaea/data/date/Time.kt
Normal file
94
src/gaea/src/main/kotlin/com/synebula/gaea/data/date/Time.kt
Normal file
@@ -0,0 +1,94 @@
|
||||
package com.synebula.gaea.data.date
|
||||
|
||||
import java.math.BigDecimal
|
||||
import java.text.ParseException
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Calendar
|
||||
import java.util.Date
|
||||
|
||||
|
||||
/**
|
||||
* 一天的时间类型。
|
||||
*
|
||||
* @author whj
|
||||
* @version 0.0.1
|
||||
* @since 2017年11月14日 下午3:45:26
|
||||
*/
|
||||
class Time(var hour: Int = 0, var minute: Int = 0, var second: Int = 0, var millisecond: Int = 0) {
|
||||
|
||||
private var milliseconds = 0L
|
||||
|
||||
/**
|
||||
* 根据默认格式字符串"HH:mm:ss"转化为时间类型。
|
||||
*
|
||||
* @param time 时间格式字符串。
|
||||
*/
|
||||
constructor(time: String) : this(time, "HH:mm:ss")
|
||||
|
||||
/**
|
||||
* 根据时间格式字符串转化为时间类型。
|
||||
*
|
||||
* @param time 时间格式字符串。
|
||||
*/
|
||||
constructor(time: String, format: String) : this() {
|
||||
val formatter = SimpleDateFormat(format)
|
||||
try {
|
||||
val value = formatter.parse(time)
|
||||
this.loadTime(value)
|
||||
} catch (e: ParseException) {
|
||||
throw RuntimeException("date string can't format to date", e)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取日期的时间。
|
||||
*/
|
||||
constructor(time: Date) : this() {
|
||||
this.loadTime(time)
|
||||
}
|
||||
|
||||
private fun loadTime(time: Date) {
|
||||
val instance = Calendar.getInstance()
|
||||
instance.time = time
|
||||
this.hour = instance.get(Calendar.HOUR_OF_DAY)
|
||||
this.minute = instance.get(Calendar.MINUTE)
|
||||
this.second = instance.get(Calendar.SECOND)
|
||||
this.millisecond = instance.get(Calendar.MILLISECOND)
|
||||
|
||||
this.milliseconds = (TimeExchanger.hourToMillisecond(this.hour) + TimeExchanger.minuteToMillisecond(this.minute)
|
||||
+ TimeExchanger.secondToMillisecond(this.second) + this.millisecond).toLong()
|
||||
}
|
||||
|
||||
/**
|
||||
* 當前时间對象减去參數中时间,得出间隔的时间
|
||||
*
|
||||
* @param other 另一个时间
|
||||
* @return
|
||||
*/
|
||||
operator fun minus(other: Time): TimeSpan {
|
||||
return TimeSpan(this.milliseconds - other.milliseconds)
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换当前时间间隔为分钟。
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
fun toMinute(): Int {
|
||||
return this.hour * 60 + this.minute
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换当前时间间隔为小时。
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
fun toHour(): Double {
|
||||
return TimeExchanger.minuteToHour(this.minute) + this.hour
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return "$hour:$minute:$second.$millisecond"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
package com.synebula.gaea.data.date
|
||||
|
||||
import com.synebula.gaea.data.type.TimeUnit
|
||||
|
||||
object TimeExchanger {
|
||||
/**
|
||||
* 转换率。分别对应:毫秒、秒、分、时、日
|
||||
*/
|
||||
private val exchangeRate = arrayOf(1, 1000, 60, 60, 24)
|
||||
|
||||
fun dayToHour(day: Int): Double {
|
||||
return this.exchange(TimeUnit.Day, TimeUnit.Hour, day.toLong())
|
||||
}
|
||||
|
||||
fun dayToMinute(day: Int): Double {
|
||||
return this.exchange(TimeUnit.Day, TimeUnit.Minute, day.toLong())
|
||||
}
|
||||
|
||||
fun dayToSecond(day: Int): Double {
|
||||
return this.exchange(TimeUnit.Day, TimeUnit.Second, day.toLong())
|
||||
}
|
||||
|
||||
fun dayToMillisecond(day: Int): Double {
|
||||
return this.exchange(TimeUnit.Day, TimeUnit.Millisecond, day.toLong())
|
||||
}
|
||||
|
||||
fun hourToDay(hour: Int): Double {
|
||||
return this.exchange(TimeUnit.Hour, TimeUnit.Day, hour.toLong())
|
||||
}
|
||||
|
||||
fun hourToMinute(hour: Int): Double {
|
||||
return this.exchange(TimeUnit.Hour, TimeUnit.Minute, hour.toLong())
|
||||
}
|
||||
|
||||
fun hourToSecond(hour: Int): Double {
|
||||
return this.exchange(TimeUnit.Hour, TimeUnit.Second, hour.toLong())
|
||||
}
|
||||
|
||||
fun hourToMillisecond(hour: Int): Double {
|
||||
return this.exchange(TimeUnit.Hour, TimeUnit.Millisecond, hour.toLong())
|
||||
}
|
||||
|
||||
fun minuteToDay(minute: Int): Double {
|
||||
return this.exchange(TimeUnit.Minute, TimeUnit.Day, minute.toLong())
|
||||
}
|
||||
|
||||
fun minuteToHour(minute: Int): Double {
|
||||
return this.exchange(TimeUnit.Minute, TimeUnit.Hour, minute.toLong())
|
||||
}
|
||||
|
||||
fun minuteToSecond(minute: Int): Double {
|
||||
return this.exchange(TimeUnit.Minute, TimeUnit.Second, minute.toLong())
|
||||
}
|
||||
|
||||
fun minuteToMillisecond(minute: Int): Double {
|
||||
return this.exchange(TimeUnit.Minute, TimeUnit.Millisecond, minute.toLong())
|
||||
}
|
||||
|
||||
fun secondToDay(second: Int): Double {
|
||||
return this.exchange(TimeUnit.Second, TimeUnit.Day, second.toLong())
|
||||
}
|
||||
|
||||
fun secondToHour(second: Int): Double {
|
||||
return this.exchange(TimeUnit.Second, TimeUnit.Hour, second.toLong())
|
||||
}
|
||||
|
||||
fun secondToMinute(second: Int): Double {
|
||||
return this.exchange(TimeUnit.Second, TimeUnit.Minute, second.toLong())
|
||||
}
|
||||
|
||||
fun secondToMillisecond(second: Int): Double {
|
||||
return this.exchange(TimeUnit.Second, TimeUnit.Millisecond, second.toLong())
|
||||
}
|
||||
|
||||
fun millisecondToDay(millisecond: Long): Double {
|
||||
return this.exchange(TimeUnit.Millisecond, TimeUnit.Day, millisecond)
|
||||
}
|
||||
|
||||
fun millisecondToHour(millisecond: Long): Double {
|
||||
return this.exchange(TimeUnit.Millisecond, TimeUnit.Hour, millisecond)
|
||||
}
|
||||
|
||||
fun millisecondToMinute(millisecond: Long): Double {
|
||||
return this.exchange(TimeUnit.Millisecond, TimeUnit.Minute, millisecond)
|
||||
}
|
||||
|
||||
fun millisecondToSecond(millisecond: Long): Double {
|
||||
return this.exchange(TimeUnit.Millisecond, TimeUnit.Second, millisecond)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 转换时间的单位
|
||||
*/
|
||||
fun exchange(source: TimeUnit, target: TimeUnit, value: Long): Double {
|
||||
var result = value.toDouble()
|
||||
if (source.ordinal > TimeUnit.Day.ordinal || target.ordinal > TimeUnit.Day.ordinal)
|
||||
throw UnsupportedOperationException("can't exchange from or exchange to month or day!")
|
||||
if (source.ordinal < target.ordinal) {
|
||||
for (i in (source.ordinal + 1)..target.ordinal) { //由小单位向上转换,转换率需要向前上提一位
|
||||
result /= exchangeRate[i]
|
||||
}
|
||||
} else {
|
||||
for (i in source.ordinal downTo (target.ordinal + 1)) {
|
||||
result *= exchangeRate[i]
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
101
src/gaea/src/main/kotlin/com/synebula/gaea/data/date/TimeSpan.kt
Normal file
101
src/gaea/src/main/kotlin/com/synebula/gaea/data/date/TimeSpan.kt
Normal file
@@ -0,0 +1,101 @@
|
||||
/**
|
||||
*
|
||||
* @author whj
|
||||
* @version 0.0.1
|
||||
* @since 2017年11月14日 下午4:51:20
|
||||
*/
|
||||
package com.synebula.gaea.data.date
|
||||
|
||||
import java.math.BigDecimal
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
*
|
||||
* @author whj
|
||||
* @version 0.0.1
|
||||
* @since 2017年11月14日 下午4:51:20
|
||||
*/
|
||||
class TimeSpan {
|
||||
private val MSEC_PER_SECOND: Double = 1000.0
|
||||
private val MSEC_PER_MINUTE: Double = MSEC_PER_SECOND * 60
|
||||
private val MSEC_PER_HOUR: Double = MSEC_PER_MINUTE * 60
|
||||
private val MSEC_PER_DAY: Double = MSEC_PER_HOUR * 24
|
||||
|
||||
/**
|
||||
* 是否为正值,默认正值
|
||||
*/
|
||||
var isPositive: Boolean = false
|
||||
var day: Int = 0
|
||||
var hour: Int = 0
|
||||
var minute: Int = 0
|
||||
var second: Int = 0
|
||||
var millisecond: Int = 0
|
||||
|
||||
val totalDays: Double
|
||||
get() {
|
||||
return this.totalMilliseconds / this.MSEC_PER_DAY
|
||||
}
|
||||
|
||||
val totalHours: Double
|
||||
get() {
|
||||
return this.totalMilliseconds / this.MSEC_PER_HOUR
|
||||
}
|
||||
|
||||
val totalMinutes: Double
|
||||
get() {
|
||||
return this.totalMilliseconds / this.MSEC_PER_MINUTE
|
||||
}
|
||||
|
||||
val totalSeconds: Double
|
||||
get() {
|
||||
return this.totalMilliseconds / this.MSEC_PER_SECOND
|
||||
}
|
||||
|
||||
var totalMilliseconds: Long = 0
|
||||
set(value) {
|
||||
this.day = (value / this.MSEC_PER_DAY).toInt()
|
||||
this.hour = ((value % this.MSEC_PER_DAY) / this.MSEC_PER_HOUR).toInt()
|
||||
this.minute = ((value % this.MSEC_PER_HOUR) / this.MSEC_PER_MINUTE).toInt()
|
||||
this.second = ((value % this.MSEC_PER_MINUTE) / this.MSEC_PER_SECOND).toInt()
|
||||
this.millisecond = (value % this.MSEC_PER_SECOND).toInt()
|
||||
field = value
|
||||
}
|
||||
|
||||
constructor(
|
||||
day: Int = 0,
|
||||
hour: Int = 0,
|
||||
minute: Int = 0,
|
||||
second: Int = 0,
|
||||
millisecond: Int = 0
|
||||
) : this(true, day, hour, minute, second, millisecond)
|
||||
|
||||
constructor(
|
||||
positive: Boolean,
|
||||
day: Int = 0,
|
||||
hour: Int = 0,
|
||||
minute: Int = 0,
|
||||
second: Int = 0,
|
||||
millisecond: Int = 0
|
||||
) {
|
||||
this.isPositive = positive
|
||||
this.day = day
|
||||
this.hour = hour
|
||||
this.minute = minute
|
||||
this.second = second
|
||||
this.millisecond = millisecond
|
||||
this.totalMilliseconds = (day * this.MSEC_PER_DAY + hour * this.MSEC_PER_HOUR
|
||||
+ minute * this.MSEC_PER_MINUTE + second * this.MSEC_PER_SECOND + millisecond).toLong()
|
||||
}
|
||||
|
||||
constructor(totalMilliseconds: Long) {
|
||||
this.isPositive = totalMilliseconds > 0
|
||||
this.totalMilliseconds = if (totalMilliseconds > 0) totalMilliseconds else -totalMilliseconds
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return if (isPositive)
|
||||
"$day $hour:$minute:$second.$millisecond"
|
||||
else
|
||||
"-$day $hour:$minute:$second.$millisecond"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.synebula.gaea.data.message
|
||||
|
||||
import java.util.Date
|
||||
|
||||
open class Message<T> {
|
||||
/**
|
||||
* 传递的业务数据
|
||||
*/
|
||||
var data: T? = null
|
||||
|
||||
/**
|
||||
* 消息时间戳
|
||||
*/
|
||||
val timestamp: Long = Date().time
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.synebula.gaea.data.message.http
|
||||
|
||||
import com.synebula.gaea.data.message.Message
|
||||
|
||||
/**
|
||||
*
|
||||
* 用来统一Http返回消息类型,通常使用json格式传递
|
||||
*
|
||||
* @param status http编码。200成功,400错误,500异常
|
||||
* @tparam T 消息数据类型
|
||||
*/
|
||||
class HttpMessage<T>(var status: Int = HttpStatus.Success.code) : Message<T>() {
|
||||
/**
|
||||
* 附带提示消息
|
||||
*/
|
||||
var message = ""
|
||||
|
||||
constructor(data: T) : this(HttpStatus.Success.code) {
|
||||
this.data = data
|
||||
}
|
||||
|
||||
constructor(status: Int, message: String) : this(status) {
|
||||
this.message = message
|
||||
}
|
||||
|
||||
constructor(status: Int, data: T, message: String) : this(status) {
|
||||
this.data = data
|
||||
this.message = message
|
||||
}
|
||||
|
||||
fun from(other: HttpMessage<T>) {
|
||||
this.status = other.status
|
||||
this.data = other.data
|
||||
this.message = message
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.synebula.gaea.data.message.http
|
||||
|
||||
/**
|
||||
* 状态类型。
|
||||
*
|
||||
* @author alex
|
||||
* @version 0.0.1
|
||||
* @since 2016年9月6日 下午3:27:55
|
||||
*/
|
||||
enum class HttpStatus(val code: Int) {
|
||||
/**
|
||||
* 成功
|
||||
*/
|
||||
Success(200),
|
||||
|
||||
/**
|
||||
* 失败
|
||||
*/
|
||||
Failure(400),
|
||||
|
||||
/**
|
||||
* 错误
|
||||
*/
|
||||
Error(500);
|
||||
|
||||
companion object {
|
||||
fun valueOf(code: Int): HttpStatus {
|
||||
return when (code) {
|
||||
200 -> HttpStatus.Success
|
||||
400 -> HttpStatus.Failure
|
||||
else -> HttpStatus.Error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.synebula.gaea.data.serializable
|
||||
|
||||
abstract class AbstractJsonSerializer : IJsonSerializable {
|
||||
|
||||
protected lateinit var data: Any
|
||||
|
||||
|
||||
/**
|
||||
* 序列化data数据。
|
||||
* 实现的serialize方法必须序列化data对象。
|
||||
*
|
||||
* @param data 需要序列号的数据。
|
||||
* @return 序列化后的json数据。
|
||||
*/
|
||||
fun serialize(data: Any): String {
|
||||
this.data = data
|
||||
return this.serialize()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.synebula.gaea.data.serializable
|
||||
|
||||
/**
|
||||
*
|
||||
* @author alex
|
||||
* @version 0.0.1
|
||||
* @since 2016年9月6日 下午3:44:24
|
||||
*/
|
||||
interface IJsonSerializable : ISerializable<String>
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.synebula.gaea.data.serializable
|
||||
|
||||
/**
|
||||
* 继承该接口的类都可以序列号对象。
|
||||
*
|
||||
* @author alex
|
||||
* @version 0.0.1
|
||||
* @since 2016年9月6日 下午3:42:01
|
||||
*/
|
||||
interface ISerializable<T> {
|
||||
/**
|
||||
* 序列化。
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
fun serialize(): T
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.synebula.gaea.data.type
|
||||
|
||||
/**
|
||||
* 数据操作类型。包括创建、更新和删除。
|
||||
* @author alex
|
||||
* @version 0.0.1
|
||||
* @since 2016年8月17日 下午2:48:29
|
||||
*/
|
||||
enum class DataOperateType {
|
||||
Create,
|
||||
|
||||
Update,
|
||||
|
||||
Remove
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.synebula.gaea.data.type
|
||||
|
||||
/*
|
||||
* 排序枚举
|
||||
*/
|
||||
enum class SortDirectionEnum {
|
||||
/*
|
||||
* 升序
|
||||
*/
|
||||
ASC,
|
||||
|
||||
/*
|
||||
* 降序
|
||||
*/
|
||||
DESC
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.synebula.gaea.data.type
|
||||
|
||||
enum class TimeUnit {
|
||||
Millisecond,
|
||||
Second,
|
||||
Minute,
|
||||
Hour,
|
||||
Day,
|
||||
Month,
|
||||
Year
|
||||
}
|
||||
17
src/gaea/src/main/kotlin/com/synebula/gaea/log/ILogger.kt
Normal file
17
src/gaea/src/main/kotlin/com/synebula/gaea/log/ILogger.kt
Normal file
@@ -0,0 +1,17 @@
|
||||
package com.synebula.gaea.log
|
||||
|
||||
import com.synebula.gaea.log.logger.*
|
||||
|
||||
/**
|
||||
* 定义日志记录的统一接口。
|
||||
*
|
||||
* @author alex
|
||||
* @version 0.0.1
|
||||
* @since 2016年8月15日 下午3:35:24
|
||||
*/
|
||||
interface ILogger : ITraceLogger, IDebugLogger, IInfoLogger, IWarnLogger, IErrorLogger {
|
||||
/**
|
||||
* @return 日志对象的Name
|
||||
*/
|
||||
val name: String
|
||||
}
|
||||
28
src/gaea/src/main/kotlin/com/synebula/gaea/log/Level.kt
Normal file
28
src/gaea/src/main/kotlin/com/synebula/gaea/log/Level.kt
Normal file
@@ -0,0 +1,28 @@
|
||||
package com.synebula.gaea.log
|
||||
|
||||
/**
|
||||
* 日志等级
|
||||
* @author Looly
|
||||
*/
|
||||
enum class Level {
|
||||
/**
|
||||
* 'TRACE' log level.
|
||||
*/
|
||||
TRACE,
|
||||
/**
|
||||
* 'DEBUG' log level.
|
||||
*/
|
||||
DEBUG,
|
||||
/**
|
||||
* 'INFO' log level.
|
||||
*/
|
||||
INFO,
|
||||
/**
|
||||
* 'WARN' log level.
|
||||
*/
|
||||
WARN,
|
||||
/**
|
||||
* 'ERROR' log level.
|
||||
*/
|
||||
ERROR
|
||||
}
|
||||
69
src/gaea/src/main/kotlin/com/synebula/gaea/log/NullLogger.kt
Normal file
69
src/gaea/src/main/kotlin/com/synebula/gaea/log/NullLogger.kt
Normal file
@@ -0,0 +1,69 @@
|
||||
package com.synebula.gaea.log
|
||||
|
||||
/**
|
||||
* 默认空日志对象,不会执行任何操作。可以让使用日志的时候可以不会为空(null)。
|
||||
*
|
||||
* @author alex
|
||||
* @version 0.0.1
|
||||
* @since 2016年9月18日 下午1:58:36
|
||||
*/
|
||||
class NullLogger : ILogger {
|
||||
|
||||
override val isTraceEnabled: Boolean
|
||||
get() = false
|
||||
|
||||
override val isDebugEnabled: Boolean
|
||||
get() = false
|
||||
|
||||
override val isInfoEnabled: Boolean
|
||||
get() = false
|
||||
|
||||
override val isWarnEnabled: Boolean
|
||||
get() = false
|
||||
|
||||
override val isErrorEnabled: Boolean
|
||||
get() = false
|
||||
|
||||
override val name: String
|
||||
get() = NullLogger::class.simpleName!!
|
||||
|
||||
override fun trace(t: Throwable) {}
|
||||
|
||||
override fun trace(format: String, vararg args: Any) {}
|
||||
|
||||
override fun trace(t: Throwable, format: String, vararg args: Any) {}
|
||||
|
||||
override fun trace(obj: Any, t: Throwable, format: String, vararg args: Any) {}
|
||||
|
||||
override fun debug(t: Throwable) {}
|
||||
|
||||
override fun debug(format: String, vararg args: Any) {}
|
||||
|
||||
override fun debug(t: Throwable, format: String, vararg args: Any) {}
|
||||
|
||||
override fun debug(obj: Any, t: Throwable, format: String, vararg args: Any) {}
|
||||
|
||||
override fun info(t: Throwable) {}
|
||||
|
||||
override fun info(format: String, vararg args: Any) {}
|
||||
|
||||
override fun info(t: Throwable, format: String, vararg args: Any) {}
|
||||
|
||||
override fun info(obj: Any, t: Throwable, format: String, vararg args: Any) {}
|
||||
|
||||
override fun warn(t: Throwable) {}
|
||||
|
||||
override fun warn(format: String, vararg args: Any) {}
|
||||
|
||||
override fun warn(t: Throwable, format: String, vararg args: Any) {}
|
||||
|
||||
override fun warn(obj: Any, t: Throwable, format: String, vararg args: Any) {}
|
||||
|
||||
override fun error(t: Throwable) {}
|
||||
|
||||
override fun error(format: String, vararg args: Any) {}
|
||||
|
||||
override fun error(t: Throwable, format: String, vararg args: Any) {}
|
||||
|
||||
override fun error(obj: Any, t: Throwable, format: String, vararg args: Any) {}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package com.synebula.gaea.log.logger
|
||||
|
||||
/**
|
||||
* DEBUG级别日志接口
|
||||
*
|
||||
* @author Looly
|
||||
*/
|
||||
interface IDebugLogger {
|
||||
/**
|
||||
* @return DEBUG 等级是否开启
|
||||
*/
|
||||
val isDebugEnabled: Boolean
|
||||
|
||||
/**
|
||||
* 打印 DEBUG 等级的日志
|
||||
*
|
||||
* @param t 错误对象
|
||||
*/
|
||||
fun debug(t: Throwable)
|
||||
|
||||
/**
|
||||
* 打印 DEBUG 等级的日志
|
||||
*
|
||||
* @param format 消息模板
|
||||
* @param args 参数
|
||||
*/
|
||||
fun debug(format: String, vararg args: Any)
|
||||
|
||||
/**
|
||||
* 打印 DEBUG 等级的日志
|
||||
*
|
||||
* @param t 错误对象
|
||||
* @param format 消息模板
|
||||
* @param args 参数
|
||||
*/
|
||||
fun debug(t: Throwable, format: String, vararg args: Any)
|
||||
|
||||
/**
|
||||
* 打印 DEBUG 等级的日志
|
||||
*
|
||||
* @param obj 输出错误对象
|
||||
* @param t 错误对象
|
||||
* @param format 消息模板
|
||||
* @param args 参数
|
||||
*/
|
||||
fun debug(obj: Any, t: Throwable, format: String, vararg args: Any)
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.synebula.gaea.log.logger
|
||||
|
||||
/**
|
||||
* ERROR级别日志接口
|
||||
* @author Looly
|
||||
*/
|
||||
interface IErrorLogger {
|
||||
/**
|
||||
* @return ERROR 等级是否开启
|
||||
*/
|
||||
val isErrorEnabled: Boolean
|
||||
|
||||
/**
|
||||
* 打印 ERROR 等级的日志
|
||||
*
|
||||
* @param t 错误对象
|
||||
*/
|
||||
fun error(t: Throwable)
|
||||
|
||||
/**
|
||||
* 打印 ERROR 等级的日志
|
||||
*
|
||||
* @param format 消息模板
|
||||
* @param args 参数
|
||||
*/
|
||||
fun error(format: String, vararg args: Any)
|
||||
|
||||
/**
|
||||
* 打印 ERROR 等级的日志
|
||||
*
|
||||
* @param t 错误对象
|
||||
* @param format 消息模板
|
||||
* @param args 参数
|
||||
*/
|
||||
fun error(t: Throwable, format: String, vararg args: Any)
|
||||
|
||||
/**
|
||||
* 打印 ERROR 等级的日志
|
||||
*
|
||||
* @param obj 输出错误对象
|
||||
* @param t 错误对象
|
||||
* @param format 消息模板
|
||||
* @param args 参数
|
||||
*/
|
||||
fun error(obj: Any, t: Throwable, format: String, vararg args: Any)
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.synebula.gaea.log.logger
|
||||
|
||||
/**
|
||||
* INFO级别日志接口
|
||||
* @author Looly
|
||||
*/
|
||||
interface IInfoLogger {
|
||||
/**
|
||||
* @return INFO 等级是否开启
|
||||
*/
|
||||
val isInfoEnabled: Boolean
|
||||
|
||||
/**
|
||||
* 打印 INFO 等级的日志
|
||||
*
|
||||
* @param t 错误对象
|
||||
*/
|
||||
fun info(t: Throwable)
|
||||
|
||||
/**
|
||||
* 打印 INFO 等级的日志
|
||||
*
|
||||
* @param format 消息模板
|
||||
* @param args 参数
|
||||
*/
|
||||
fun info(format: String, vararg args: Any)
|
||||
|
||||
/**
|
||||
* 打印 INFO 等级的日志
|
||||
*
|
||||
* @param t 错误对象
|
||||
* @param format 消息模板
|
||||
* @param args 参数
|
||||
*/
|
||||
fun info(t: Throwable, format: String, vararg args: Any)
|
||||
|
||||
/**
|
||||
* 打印 INFO 等级的日志
|
||||
*
|
||||
* @param obj 输出错误对象
|
||||
* @param t 错误对象
|
||||
* @param format 消息模板
|
||||
* @param args 参数
|
||||
*/
|
||||
fun info(obj: Any, t: Throwable, format: String, vararg args: Any)
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.synebula.gaea.log.logger
|
||||
|
||||
/**
|
||||
* TRACE级别日志接口
|
||||
*
|
||||
* @author Looly
|
||||
*/
|
||||
interface ITraceLogger {
|
||||
/**
|
||||
* @return TRACE 等级是否开启
|
||||
*/
|
||||
val isTraceEnabled: Boolean
|
||||
|
||||
/**
|
||||
* 打印 TRACE 等级的日志
|
||||
*
|
||||
* @param t 错误对象
|
||||
*/
|
||||
fun trace(t: Throwable)
|
||||
|
||||
/**
|
||||
* 打印 TRACE 等级的日志
|
||||
*
|
||||
* @param format 消息模板
|
||||
* @param args 参数
|
||||
*/
|
||||
fun trace(format: String, vararg args: Any)
|
||||
|
||||
/**
|
||||
* 打印 TRACE 等级的日志
|
||||
*
|
||||
* @param t 错误对象
|
||||
* @param format 消息模板
|
||||
* @param args 参数
|
||||
*/
|
||||
fun trace(t: Throwable, format: String, vararg args: Any)
|
||||
|
||||
/**
|
||||
* 打印 TRACE 等级的日志
|
||||
*
|
||||
* @param obj 输出错误对象
|
||||
* @param t 错误对象
|
||||
* @param format 消息模板
|
||||
* @param args 参数
|
||||
*/
|
||||
fun trace(obj: Any, t: Throwable, format: String, vararg args: Any)
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.synebula.gaea.log.logger
|
||||
|
||||
/**
|
||||
* WARN级别日志接口
|
||||
* @author Looly
|
||||
*/
|
||||
interface IWarnLogger {
|
||||
/**
|
||||
* @return WARN 等级是否开启
|
||||
*/
|
||||
val isWarnEnabled: Boolean
|
||||
|
||||
/**
|
||||
* 打印 WARN 等级的日志
|
||||
*
|
||||
* @param t 错误对象
|
||||
*/
|
||||
fun warn(t: Throwable)
|
||||
|
||||
/**
|
||||
* 打印 WARN 等级的日志
|
||||
*
|
||||
* @param format 消息模板
|
||||
* @param args 参数
|
||||
*/
|
||||
fun warn(format: String, vararg args: Any)
|
||||
|
||||
/**
|
||||
* 打印 WARN 等级的日志
|
||||
*
|
||||
* @param t 错误对象
|
||||
* @param format 消息模板
|
||||
* @param args 参数
|
||||
*/
|
||||
fun warn(t: Throwable, format: String, vararg args: Any)
|
||||
|
||||
/**
|
||||
* 打印 WARN 等级的日志
|
||||
*
|
||||
* @param obj 输出错误对象
|
||||
* @param t 错误对象
|
||||
* @param format 消息模板
|
||||
* @param args 参数
|
||||
*/
|
||||
fun warn(obj: Any, t: Throwable, format: String, vararg args: Any)
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.synebula.gaea.test
|
||||
|
||||
import com.synebula.gaea.data.code.SnowflakeCode
|
||||
import junit.framework.TestCase
|
||||
|
||||
class CodeGenerateTest : TestCase() {
|
||||
fun testSnowflake() {
|
||||
val snowflakeCode = SnowflakeCode(1, 1)
|
||||
for (i in 0..10) {
|
||||
Thread.sleep(1000)
|
||||
println(snowflakeCode.generate())
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user