前面介绍了,使用扩展函数可以很方便地扩充数组Array的处理功能,例如交换两个数组元素、求数组的最大元素等等。那么除了数组之外,日期和时间的相关操作,也是很常见的,比如获取当前日期,获取当前时间、获取指定格式的日期时间等等。因此,基本上每个Java书写的Android工程,都需要一个类似DateUtil.java的工具类,用于获得不同格式的时间字符串,下面代码便是一个实现了基础时间拼接的日期工具类例子:

public class DateUtil {
//获取当前完整的日期和时间
public static String getNowDateTime() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return sdf.format(new Date());
} //获取当前时间
public static String getNowTime() {
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
return sdf.format(new Date());
} //获取当前时间(精确到毫秒)
public static String getNowTimeDetail() {
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss.SSS");
return sdf.format(new Date());
}
}

注意到上述代码的时间格式存在大小写字母揉合的情况,为避免混淆,有必要对这些格式字符串进行取值说明,详述如下:

小写的yyyy:表示四位年份数字,如1949、2017等等。
大写的MM:表示两位月份数字,如01表示一月份,12表示12月份。
小写的dd:表示两位日期数字,如08表示当月八号,26表示当月二十六号。
大写的HH:表示24小时制的两位小时数字,如19表示晚上七点。
小写的hh:表示12小时制的两位小时数字,如06可同时表示早上六点与傍晚六点;因为12小时制的表达会引发歧义,所以实际开发中很少这么使用。
小写的mm:表示两位分钟数字,如30表示某点三十分。
小写的ss:表示两位秒钟数字。
大写的SSS:表示三位毫秒数字。

其余的横线“-”、空格“ ”、冒号“:”、点号“.”等字符,仅仅是连接符,方便观看各种单位的时间数字而已;对于中文世界来说,也可采用形如“yyyy年MM月dd日HH时mm分ss秒”的格式。

现在使用Kotlin的扩展函数,无需声明专门的DateUtil工具类,直接写几个系统日期Date类的扩展函数,即可实现日期时间格式转换的功能,改写后的Date类扩展函数举例如下:

//方法名称前面的Date.表示该方法扩展自Date类
//返回的日期时间格式形如2017-10-01 10:00:00
fun Date.getNowDateTime(): String {
val sdf = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
return sdf.format(this)
} //只返回日期字符串
fun Date.getNowDate(): String {
val sdf = SimpleDateFormat("yyyy-MM-dd")
return sdf.format(this)
} //只返回时间字符串
fun Date.getNowTime(): String {
val sdf = SimpleDateFormat("HH:mm:ss")
return sdf.format(this)
} //返回详细的时间字符串,精确到毫秒
fun Date.getNowTimeDetail(): String {
val sdf = SimpleDateFormat("HH:mm:ss.SSS")
return sdf.format(this)
} //返回开发者指定格式的日期时间字符串
fun Date.getFormatTime(format: String=""): String {
var ft: String = format
val sdf = if (!ft.isEmpty()) SimpleDateFormat(ft)
else SimpleDateFormat("yyyyMMddHHmmss")
return sdf.format(this)
}

那么调用这些Date类的扩展函数,也不会很复杂,像下面代码通过“Date().getNowDate()”、“Date().getNowTime()”等方法就能获取到相应的日期和时间字符串:

    btn_extend_date.setOnClickListener {
//以下方法调用自ExtendDate.kt,采取了扩展函数的方式
tv_function_result.text = "扩展函数:" + when (count++%5) {
0 -> "当前日期时间为${Date().getNowDateTime()}"
1 -> "当前日期为${Date().getNowDate()}"
2 -> "当前时间为${Date().getNowTime()}"
3 -> "当前毫秒时间为${Date().getNowTimeDetail()}"
else -> "当前中文日期时间为${Date().getFormatTime("yyyy年MM月dd日HH时mm分ss秒")}"
}
}

虽然说上面的扩展函数已经实现相关日期信息的获取,但是调用方式稍显繁琐,比如“Date().getNowDate()”这个日期方法,一共占了四个括号,容易使人产生密集恐惧症。况且这些函数必须从某个已存在的类扩展而来,倘若没有可依赖的具体类,也就无法书写扩展函数了。所以,Java编码常见的***Util工具类,某种程度上反而更灵活、适应面更广,那么Kotlin有没有专门的工具类写法呢?

作为一个后起之秀,Kotlin的设计者显然考虑到了这种情况,并且给出了有针对性的解决方案。在Java之中,不管是工具类还是实体类抑或是业务类,统统采用class关键字,如果是工具类的话,其内部的方法都加上static修饰符,表示该类中的方法无需构造即可调用。如此这般,搞得Java的class像个万金油,啥都能做,却啥都要特殊处理。有鉴于此,Kotlin将工具类的用法提炼了出来,既然这个东西仅仅是作为工具,那么一旦制定了规格就不能再改变了,不能构造也不能修改。故而Kotlin使用对象object关键字加以修饰,并称之为“单例对象”,其实相当于Java的工具类。
单例对象的用法跟传统的类比较,像是一种阉割了的简化类,倘若把普通类比做App,则单例对象好比小程序,用完即走,不留下一抹痕迹。譬如前面提到的getNowDateTime方法,在单例对象中会分解成两个部分,第一个部分是字符串nowDateTime的变量声明,第二个部分是紧跟着的获取变量值的get方法。外部访问单例对象的内部变量,object会自动调用该变量的get方法,下面是采取单例对象改写后的日期时间工具代码:

//关键字object用来声明单例对象,就像Java中开发者自己定义的Utils工具类。
//其内部的属性等同于Java中的static静态属性,外部可直接获取属性值。
object DateUtil { //声明一个当前日期时间的属性,
//返回的日期时间格式形如2017-10-01 10:00:00
val nowDateTime: String
//外部访问DateUtil.nowDateTime时,会自动调用nowDateTime附属的get方法得到它的值
get() {
val sdf = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
return sdf.format(Date())
} //只返回日期字符串
val nowDate: String
get() {
val sdf = SimpleDateFormat("yyyy-MM-dd")
return sdf.format(Date())
} //只返回时间字符串
val nowTime: String
get() {
val sdf = SimpleDateFormat("HH:mm:ss")
return sdf.format(Date())
} //返回详细的时间字符串,精确到毫秒
val nowTimeDetail: String
get() {
val sdf = SimpleDateFormat("HH:mm:ss.SSS")
return sdf.format(Date())
} //返回开发者指定格式的日期时间字符串
fun getFormatTime(format: String=""): String {
val ft: String = format
val sdf = if (!ft.isEmpty()) SimpleDateFormat(ft)
else SimpleDateFormat("yyyyMMddHHmmss")
return sdf.format(Date())
}
}

外部若要访问单例对象的变量值,直接调用“对象名称.变量名称”即可,此时晃瞎眼的括号都不见踪影,一下子干净了许多。调用单例对象的代码例子如下所示:

    btn_object_date.setOnClickListener {
//以下方法调用自DateUtil.kt,采取了单例对象的方式
tv_function_result.text = "单例对象:" + when (count++%5) {
0 -> "当前日期时间为${DateUtil.nowDateTime}"
1 -> "当前日期为${DateUtil.nowDate}"
2 -> "当前时间为${DateUtil.nowTime}"
3 -> "当前毫秒时间为${DateUtil.nowTimeDetail}"
else -> "当前中文日期时间为${DateUtil.getFormatTime("yyyy年MM月dd日HH时mm分ss秒")}"
}
}

  

Kotlin入门(18)利用单例对象获取时间的更多相关文章

  1. Kotlin入门(28)Application单例化

    Application是Android的又一大组件,在App运行过程中,有且仅有一个Application对象贯穿应用的整个生命周期,所以适合在Application中保存应用运行时的全局变量.而开展 ...

  2. Scala入门1(单例对象和伴生类)

    一.Hello World程序的执行原理 参考http://blog.csdn.net/zhangjg_blog/article/details/22760957 object HelloWorld{ ...

  3. 【Cocos2d-X游戏实战开发】捕鱼达人之单例对象的设计(二)

    本系列学习教程使用的是cocos2d-x-2.1.4(最新版为cocos2d-x-2.1.5)    博主发现前两个系列的学习教程被严重抄袭,在这里呼吁大家请尊重开发者的劳动成果, 转载的时候请务必注 ...

  4. iOS 如何创建单例对象

    一.什么是单例? 说到单例我就想起了我的java啊 ,不禁感叹起我的大学时光,学了4年的java开发,到现在还是放弃了我的java,踏入了iOS的行列. 算了,入正轨,我现在正是铁树银花的青春美少女, ...

  5. 【cocos2d-js官方文档】二十五、Cocos2d-JS v3.0中的单例对象

    为何将单例模式移除 在Cocos2d-JS v3.0之前.全部API差点儿都是从Cocos2d-x中移植过来的,这是Cocos2d生态圈统一性的重要一环.可惜的是,这样的统一性也在非常大程度上限制了C ...

  6. Spring IoC 中的(Singleton)单例对象创建过程探索

    前言 之前将spring framework 源码导入了idea,后来折腾调试了一下,于是研究了一下最简单的singleton对象在spring中是如何创建的.这里所谓的简单,就是指无属性注入,无复杂 ...

  7. atitit.guice3 绑定方式打总结生成非单例对象toInstance toProvider区别 v2 pb29

    atitit.guice3 绑定方式打总结生成非单例对象toInstance toProvider区别 v2 pb29 1. 三 绑定方式的介绍1 2. To接口,链式绑定,用的最多的1 3. toC ...

  8. 探索Scala(3)-- 单例对象

    研究一下Scala语言的单例对象(Singleton Objects),为下一篇文章做准备. static不是keyword 上一篇文章提到过,interface并非Scala语言keyword,能够 ...

  9. JS单例对象与构造函数对象的区别

    JavaScript对象有几种: 内置对象如Global,Math对象等等. 本地对象如Object.Function.Array.String.Boolean.Number.Date.RegExp. ...

随机推荐

  1. xtrabackup备份mysql-2 增量备份

    ---恢复内容开始--- 增量备份 ---恢复内容结束---] 增量备份恢复 1,重演日志 2,恢复数据

  2. idea : shorten command line

    [官方文档]:IntelliJ IDEA 2017.3 EAP: Configurable command line shortener and more 如果类路径太长,或者有许多VM参数,程序就无 ...

  3. .NET手记-Autofac进阶(属性和方法注入 Property and Method Injection)

    尽管构造函数参数注入是传递参数值给当前构造的组件的优先方式,但是你也可以使用属性或者方法注入来提供参数值. 属性注入使用可写入的变量而不是构造函数参数来完成注入.方法注入则通过方法来设置依赖项. 属性 ...

  4. 关于c++11中的thread库

    c++11中新支持了thread这个库,常见的创建线程.join.detach都能支持. join是在main函数中等待线程执行完才继续执行main函数,detach则是把该线程分离出来,不管这个线程 ...

  5. 【Collection、泛型】

    [Collection.泛型] 主要内容 Collection集合 迭代器 增强for 泛型 第一章 Collection集合 1.1 集合概述 集合:集合是java中提供的一种容器,可以用来存储多个 ...

  6. 14-01 Java matches类,Pattern类,matcher类

    Pattern类 正则表达式常见规则 A:字符 x 字符 x.举例:'a'表示字符a \\ 反斜线字符. \n 新行(换行)符 ('\u000A') \r 回车符 ('\u000D') B:字符类 [ ...

  7. 如何更优雅的在kubernetes平台下记录日志

    背景 传统项目里面记录日志大多数都是将日志记录到日志文件,升级到分布式架构以后,日志开始由文件转移到elasticsearch(es)中来存储,达到集中管理.在kubernetes平台里面把日志记录到 ...

  8. JodaTimeUtil日期处理工具类(简单、实用)

    一.maven依赖 <!--joda time--> <dependency> <groupId>joda-time</groupId> <art ...

  9. kubernetes系列(一)安装和配置

    谈到kubernetes(或者说k8s)不得不提到云计算.虚拟化以及容器技术,相关介绍网上一大堆,不再赘述.而kubernetes的出现就是为了高效的管理云端运行的docker容器. 环境 docke ...

  10. 修改git分支名称

    场景:将分支名称为 oldbranch 改为 newbranch 步骤: 1.将本地分支oldbranch切一个分支到本地 git branch -m oldbranch newbranch 2.删除 ...