如何从NSTimeZone获取GNU Lib C TZ格式输出以同步iOS设备时区?
问题描述
我需要将iOS设备上的时区信息设置到一台远程时钟上。
该远程时钟仅支持GNU lib C TZ格式,格式规则为:std offset dst [offset],start[/time],end[/time]
示例:EST+5EDT,M3.2.0/2,M11.1.0/2
因此我需要在Swift中从NSTimeZone.local本地时区生成符合上述规则的字符串,但目前无法访问IANA TZ数据库中的当前时区规则来生成对应输出。
请问是否可以不在应用中本地缓存TZ数据库的前提下实现该需求?
更新:
我尝试查询其他编程语言的相关实现也没有找到有效方案,目前找到的最优思路是在Linux中解析tzfile,自行构建包含对应信息的NSDictionary。
解答
可以实现,不需要在应用内单独缓存IANA TZ数据库,iOS系统自带的TimeZone(原NSTimeZone)框架已经暴露了生成GNU libc TZ格式字符串需要的所有字段,直接调用系统API即可获取所有参数,步骤如下:
格式参数拆解对应系统API
GNU TZ的标准格式为 std offset dst [offset],start[/time],end[/time],每个字段的获取方式:
- std:标准时区缩写,取非夏令时日期的时区缩写即可,比如构造当年1月1日的
Date调用TimeZone.local.abbreviation(for: date)获取 - offset:标准时区相对于UTC的偏移,注意GNU TZ的偏移符号和系统返回的
secondsFromGMT符号相反:系统返回的是UTC到本地时区的秒差,GNU TZ需要的是本地时区转UTC的小时差,直接用-secondsFromGMT / 3600计算即可,非整小时偏移按实际格式补全分钟即可 - dst:夏令时时区缩写,构造当年7月1日的
Date调用abbreviation(for:)获取即可 - [offset]:夏令时相对于标准时的偏移,默认差1小时可省略,否则按上述偏移规则计算填写
- start[/time]:夏令时开始规则,通过
TimeZone.local.nextDaylightSavingTimeTransition(after: 当年年初日期)获取开始日期,再将日期转成M<月份>.<当月第几周>.<周几>格式,默认生效时间为2点的话后缀加/2即可 - end[/time]:夏令时结束规则,同上获取结束日期后转成对应格式即可
特殊情况处理
如果当前时区不支持夏令时,直接返回std offset格式的字符串即可,不需要补全后面的夏令时相关参数。
你提到的解析tzfile自行构建字典的方案没有必要,系统框架已经完成了底层tzfile的解析逻辑,直接调用上层API即可,既减少开发量也避免自己解析出错的风险。
内容的提问来源于stack exchange,提问作者MandoMando
相关产品推荐
相关产品推荐

