撸一个kotlin DSL 日期库
2021-04-21 本文已影响0人
折剑游侠
很多小伙伴还是在用JAVA的写法写kotlin,当然也没啥毛病;but这样一来kotlin的很多语法特性都没能得到充分发挥,用kotlin去重写一遍JAVA的逻辑也没有丝毫意义。
下面提供一个思路,期望达到的效果:用自然语言的方式进行api调用。
3 天 前
很明显,这种调用方式需要一个中缀函数。
kotlin中Map初始化时可以这样写
mutableMapOf("key" to "value")
点进to
函数看一下实现,关于中缀函数定义
public infix fun <A, B> A.to(that: B): Pair<A, B> = Pair(this, that)
不出意外,是个中缀函数,支持A 方法名 B
的调用方式
接下来实现日期函数,需要为Int类型提供一个中缀函数:天
infix fun Int.天(): String {
return ""
}
但是编译器会报错,中缀函数有且只有一个参数。方法还需要一个参数,前/后
。
infix fun Int.天(format: String): String {
return ""
}
用string肯定不太行,调用需要双引号,虽然可以用@StringDef
限制取值范围。
3 天 "前"
当然是选择枚举啊
enum class DateFormat {
前,
后
}
infix fun Int.天(dateFormat: DateFormat): String {
return ""
}
调用时很僵硬的带上了枚举类名
3 天 DateFormat.前
再次改造
enum class DateFormat {
AGO,
AFTER
}
val 前 = DateFormat.AGO
val 后 = DateFormat.AFTER
哎?好起来了
3 天 前
接下来就是函数实现了
val sdf: SimpleDateFormat
get() = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault())
infix fun Int.天(dateFormat: DateFormat): String {
return when (dateFormat) {
DateFormat.AGO -> {
Calendar.getInstance().run {
add(Calendar.DAY_OF_YEAR, -this@天)
sdf.format(timeInMillis)
}
}
DateFormat.AFTER -> {
Calendar.getInstance().run {
add(Calendar.DAY_OF_YEAR, +this@天)
sdf.format(timeInMillis)
}
}
}
}
CV大法,实现下周、月、年
中缀函数
infix fun Int.周(dateFormat: DateFormat): String {
return when (dateFormat) {
DateFormat.AGO -> {
Calendar.getInstance().run {
add(Calendar.WEEK_OF_YEAR, -this@周)
sdf.format(timeInMillis)
}
}
DateFormat.AFTER -> {
Calendar.getInstance().run {
add(Calendar.WEEK_OF_YEAR, +this@周)
sdf.format(timeInMillis)
}
}
}
}
infix fun Int.月(dateFormat: DateFormat): String {
return when (dateFormat) {
DateFormat.AGO -> {
Calendar.getInstance().run {
add(Calendar.MONTH, -this@月)
sdf.format(timeInMillis)
}
}
DateFormat.AFTER -> {
Calendar.getInstance().run {
add(Calendar.MONTH, +this@月)
sdf.format(timeInMillis)
}
}
}
}
infix fun Int.年(dateFormat: DateFormat): String {
return when (dateFormat) {
DateFormat.AGO -> {
Calendar.getInstance().run {
add(Calendar.YEAR, -this@年)
sdf.format(timeInMillis)
}
}
DateFormat.AFTER -> {
Calendar.getInstance().run {
add(Calendar.YEAR, +this@年)
sdf.format(timeInMillis)
}
}
}
}
看下效果
log(3 天 前)
log(3 天 后)
log(1 周 前)
log(1 周 后)
log(5 月 前)
log(5 月 后)
log(10 年 前)
log(10 年 后)
下面可以按照自己的想法实现KDate日期库了