前面介绍了,使用扩展函数可以很方便地扩充数组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. OpenStack-Ocata版+CentOS7.6 云平台环境搭建 — 3.安装配置OpenStack认证服务(keystone)

    节点配置信息说明: 控制节点:controller: IP:192.168.164.128 hostname&hosts:likeadmin 计算加点:Nova: IP:192.168.164 ...

  2. vue安装及axios、stylus、iview的安装流程整理

    现在做的项目中主要用到以下几个安装包,所以整理下流程: 使用命令行工具npm新创建一个vue项目 vue中axios的安装和使用 在vue项目中stylus的安装及使用 如何在vue中全局引入styl ...

  3. rest framework 尝鲜

    安装 pip install djangorestframework 新建项目 python manage.py startapp idcs 添加模型(models.py) class Idcs(mo ...

  4. 【sping揭秘】22、事务管理

    有关事务的楔子 什么是事务??? 事务就是以可控的方式对数据资源进行访问的一组操作. 事务本身持有四个限定属性 原子性,一致性,隔离性,持久性 事务家族 Resource Manager  RM,负责 ...

  5. Java异常处理设计(三)

    接着上一篇讲. 一个异常日志处理的例子: 抛出异常的地方为: try{ ... ...//省略N行 }catch( Exception e){ throw new RuntimeException ( ...

  6. SqlServer 循环建表、删除表、更新表

    常用于分库分表 1.批量删除 declare @outter int declare @inner int ) ) ) begin set @tablePrefix='BankPayOrder_'+c ...

  7. 使用Spring Boot开发 “Hello World” Web应用

    环境准备 由于现在很多IDE都支持Maven, 所以我们将使用Maven构建该工程: 开始之前,需要先安装Java和Maven: 本工程将基于Spring Boot 1.4.3.RELEASE开发,推 ...

  8. Kafka项目实战-用户日志上报实时统计之编码实践

    1.概述 本课程的视频教程地址:<Kafka实战项目之编码实践>  该课程我以用户实时上报日志案例为基础,带着大家去完成各个KPI的编码工作,实现生产模块.消费模块,数据持久化,以及应用调 ...

  9. Maven项目打包成可执行Jar文件

    在使用Maven完成项目以后,如果需要打包成可执行的Jar文件,我们通过eclipse的导出很麻烦,还得指定入口文件的位置,还得说明依赖的jar包,既然都使用Maven了,很重要的一个目的就是让这些繁 ...

  10. Linux下搭建DNS缓存服务器

    CentOS 6.10搭建本地DNS缓存服务器系统环境 1 [root@test ~]# cat /etc/redhat-release 2 CentOS release 6.10 (Final) 3 ...