重新初始化项目

This commit is contained in:
2019-09-02 17:08:06 +08:00
commit fb070f07ea
32 changed files with 1356 additions and 0 deletions

View File

@@ -0,0 +1,2 @@
dependencies {
}

View File

@@ -0,0 +1,21 @@
package com.synebula.gaea.data
/**
* 对象转换器,支持对象之间的转换。
*
* @author alex
* @version 0.1
* @since 2018 18-2-2
*/
interface IObjectConvertor {
/**
* 转换源对象到目标对象。
*
* @param src 源对象。
* @param dest 目标对象。
* @param <T> 目标对象类型。
* @return 目标对象
</T> */
fun <T> convert(src: Any, dest: Class<T>): T
}

View File

@@ -0,0 +1,58 @@
package com.synebula.gaea.data
import com.synebula.gaea.data.type.Status
import java.util.*
/**
*
* @author reize
* @version 0.0.1
* @since 2016年9月6日 下午3:47:35
*/
open class StatusData<T> {
var code: Status
set(value) {
field = value
this.status = value.code
}
var status: Int
var message: String = ""
var data: T? = null
val timestamp = Date().time
/**
* ctor
*/
constructor(code: Status) {
this.code = code
this.status = code.code
}
constructor() : this(Status.success) {
}
/**
* @param data 数据
*/
constructor(data: T) : this(Status.success) {
this.data = data
}
/**
* @param status 状态
* @param message 消息
*/
constructor(status: Status, message: String) : this(status) {
this.message = message
}
/**
* @param status 状态
* @param message 消息
* @param data 数据
*/
constructor(status: Status, message: String, data: T) : this(status) {
this.message = message
this.data = data
}
}

View File

@@ -0,0 +1,49 @@
package com.synebula.gaea.data.cache
import java.util.Date
/**
*
* @author reize
* @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
}
}

View File

@@ -0,0 +1,14 @@
package com.synebula.gaea.data.cache
/**
* 缓存接口。
*
* @author reize
* @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
}

View File

@@ -0,0 +1,25 @@
package com.synebula.gaea.data.code
/**
* 组合编号,根据模板组合生成编号。
*
* @author reize
* @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()
}
}

View File

@@ -0,0 +1,23 @@
package com.synebula.gaea.data.code
import java.text.SimpleDateFormat
import java.util.Date
/**
* @author reize
* @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()))
}
}

View File

@@ -0,0 +1,45 @@
package com.synebula.gaea.data.code
import java.util.Random
/**
* 固定长度随机编号生成。
* @author reize
* @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()
}
}

View File

@@ -0,0 +1,47 @@
package com.synebula.gaea.data.code
/**
* 序列编号,自增的编号。
*
* @author reize
* @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)
}
}

View File

@@ -0,0 +1,17 @@
package com.synebula.gaea.data.code
import java.util.UUID
/**
* 全球唯一编号生成。
*
* @author reize
* @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(), "")
}
}

View File

@@ -0,0 +1,17 @@
package com.synebula.gaea.data.code
/**
* 继承本接口的类,都能实现编号生成工作。
*
* @author reize
* @version 0.0.1
* @since 2016年10月24日 上午10:41:03
*/
interface ICodeGenerator<T> {
/**
* 生成编号。
*
* @return
*/
fun generate(): T
}

View File

@@ -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
}
}

View File

@@ -0,0 +1,18 @@
package com.synebula.gaea.data.code
/**
* 默认值编号,返回默认值。
*
* @author reize
* @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
}
}

View File

@@ -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
}
}

View File

@@ -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)
}

View 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()
/**
* 从ate格式转化
*/
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)
}
/**
* 从ate格式转化
*/
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)
}
}
/**
* 从ate格式转化。需要注意的是月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)
}
}

View 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"
}
}

View File

@@ -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
}
}

View 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"
}
}

View File

@@ -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()
}
}

View File

@@ -0,0 +1,9 @@
package com.synebula.gaea.data.serializable
/**
*
* @author reize
* @version 0.0.1
* @since 2016年9月6日 下午3:44:24
*/
interface IJsonSerializable : ISerializable<String>

View File

@@ -0,0 +1,17 @@
package com.synebula.gaea.data.serializable
/**
* 继承该接口的类都可以序列号对象。
*
* @author reize
* @version 0.0.1
* @since 2016年9月6日 下午3:42:01
*/
interface ISerializable<T> {
/**
* 序列化。
*
* @return
*/
fun serialize(): T
}

View File

@@ -0,0 +1,15 @@
package com.synebula.gaea.data.type
/**
* 数据操作类型。包括创建、更新和删除。
* @author reize
* @version 0.0.1
* @since 2016年8月17日 下午2:48:29
*/
enum class DataOperateType {
Create,
Update,
Remove
}

View File

@@ -0,0 +1,16 @@
package com.synebula.gaea.data.type
/*
* 排序枚举
*/
enum class SortDirectionEnum {
/*
* 升序
*/
ASC,
/*
* 降序
*/
DESC
}

View File

@@ -0,0 +1,36 @@
package com.synebula.gaea.data.type
/**
* 状态类型。
*
* @author reize
* @version 0.0.1
* @since 2016年9月6日 下午3:27:55
*/
enum class Status(val code: Int) {
/**
* 成功
*/
success(200),
/**
* 失败
*/
failure(400),
/**
* 错误
*/
error(500);
companion object {
fun valueOf(code: Int): Status {
return when (code) {
200 -> Status.success
400 -> Status.failure
else -> Status.error
}
}
}
}

View File

@@ -0,0 +1,11 @@
package com.synebula.gaea.data.type
enum class TimeUnit {
Millisecond,
Second,
Minute,
Hour,
Day,
Month,
Year
}

View File

@@ -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())
}
}
}