美文网首页Android 复习学习使用
撸一个kotlin DSL 日期库

撸一个kotlin DSL 日期库

作者: 折剑游侠 | 来源:发表于2021-04-21 15:33 被阅读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日期库了

    相关文章

      网友评论

        本文标题:撸一个kotlin DSL 日期库

        本文链接:https://www.haomeiwen.com/subject/jgqzlltx.html