首页 > 技术文章 > iOS 获取日期 日期格式化 24小时格式

huangzhengguo 2018-09-15 16:16 原文

由于项目需要,需要获取去设备的当前时间,组成一个字符串,比如 2018年9月15日 15点30分30秒,需要转换成字符串:180915153030。

很简单的一个需求,于是就使用了日期格式话当前时间:

let currentDate: Date! = Date()
let dateFormatter = DateFormatter.init()
        
dateFormatter.dateFormat = "yyMMddHHmmss"
        
let timeStr = dateFormatter.string(from: currentDate)

就是这段代码,自己测试后没有问题,就提交了,并上线了,可是到客户那出现了问题。由于我这里不是展示timeStr,而是和另外一个需求一起使用,导致另外一个功能失败。这个隐藏的bug让我找了一个多月的时间。在自己手机上测试,找了好几个手机测试都没有问题。客户那使用时出现问题,也没有往这想,会是这段代码出现问题。最终发现是和手机设置的日期格式(12小时制和24小时制有关系)及日历选择。

下面就来分析在不同情况下获取到的字符串都啥样。

1)在设置->通用->日期和时间设置24-Hour Time关闭

获取到的时间字符串为:18091534200 pm,可以发现yyMMddHHmmss这个格式对时间进行了格式化,但是其中的小时没有格式化为24小时制的,而且后面还多了一个空格及pm表示下午,可见没有获得我们想要的格式,用户的日期格式的设置会影响到我们获取到的时间。

 

2)打开24-Hour Time

获取到的时间字符串为:180915154617(时间是运行程序时的时间,所以和上面不同,下同),很明显,这个获得了我们想要的字符串。

 

3)在设置->通用->语言和地区中有个日历(Calendar)有三种选择:Gregorian也就是我们用的公历,上面两种情况都是在公历下输出的结果;Japanese也就是日本的日历,目前叫平成年,2018年就是平成30年。Buddhist佛教日历。

那好我们就设置下日本日历看看获取到的是啥:

24小时制下:300915155438,可见除了年份不对外,其它都对,年份是30,也就是平成30年

12小时制下:300915155800,可以发现并没有上面的pm标记,也就是这个问题导致我这个bug迟迟没被发现,只有在设备语言设置为英文并且是公历的情况下才会输出pm后缀,平时测试用的简体中文设置,12小时制,所以客户出现的错误,我这怎么也复现不了。

咱们再看看佛历的输出:

24小时制下:610915160205,可以发现不仅年份不一样,日以及时间都不对,这个时间是按佛历计算的,有兴趣的话可以查查佛历。

12小时制下:610915160406,同上,同时也没有出现pm后缀。

说了这么多,怎么才能获取到需要的时间字符串呢?

解决方法如下:

1).设置dateFormatter的calendar属性,就是制定日历,直接指定公历,这样避免了使用用户的设置

dateFormatter.calendar = Calendar.init(identifier: .gregorian)

2)这样还不够,如果只设置上面的日历属性获取到的时间字符串还是带有pm后缀,而且在12小时制下获取到的字符串也不对,小时并没有按照24小时格式化,还需要设置local属性,本地化

dateFormatter.locale = Locale.init(identifier: "NL")

上面是设置格式的本地化属性,其中NL是荷兰的缩写,这个解决方法是在网站找到的,设置为NL的话,格式时间时就是HH来格式化的,这个应该设置别的国家也可以。至此,只要设置到上面两个属性,格式化得到的就是我们想要的格式yyMMHHmmss格式了。

另外一种解决方法:

        // 获取当前时间
        let currentDate: Date! = Date()
        // 一定要使用公历日历gregorian
        let calendar: Calendar! = Calendar.init(identifier: .gregorian)
        let weekComps: DateComponents! = calendar.dateComponents([.year, .month, .day, .weekday - 1, .hour, .minute, .second], from: currentDate)

上面获取的DateComponents对象,里面有各个日期字段,然后通过拼接字符串即可得到想要的字符串,这里不用设置本地化,只需指定公历即可,在哪种语言下获取的都是24小时格式的。上面这个还获取了周,其中周需要减1才能得到当前的星期数。

18091534200 pm

18091534200

推荐阅读