时区之痒 - 从手机GPS模块获取的时间,真的是北京时间么?


去年互联网地图行业开始引入众包模式,国内比较大的地图商,比如四维图新、高德地图、百度地图纷纷开始推出UGC应用,众包给用户采集门址、公交站等信息,并按照工作量给与采集者一定的回报。我曾经玩过某德推出的“道路寻宝”APP,应用内部集成了道路拍拍、门址采集、公交拍拍、POI任务等。该应用有如下限制:(1)为了防止作弊,采集者必须打开GPS,才能拍摄门牌号。(2)为了保证图片清晰,采集工作只能在日出后半小时至日落前半小时内进行。问题在于,应用仅仅读取手机的时间进行日出日落时间判断。在一个用户线上会议,远在新疆用户抱怨,往往烈日当头采集就被强制结束。PS:其实还有一个BUG他没有发现:太阳升起之前,采集就已经放开了;而且如果你是位于东北三省东部的用户,在日落后依然可以采集~

那么问题到底出在什么地方?先从时区谈起。

理论时区

众所周知,由于时差问题,世界各地的日出日时刻是不同的。然而,每个国家或地区,都喜欢把日出时刻定在5-7点左右,把日落时刻定在16-19点左,甚至有的地区为了迁就这样的民间习惯,还设置了夏令时这样的概念。这样一来,使用全球统一的格林威治标准时间,就只能停留在专业领域,而在民用领域,大家各自为政,使用适合自己的时间。这就产生了时区。以穿越英国伦敦格林威治的本初子午线为基准,向东向西分别设置了12个时区,每个时区的“时间”数值相差一个小时。

理论时区以被15整除的子午线为中心,向东西两侧延伸7.5度,即每15°划分一个时区,这是理论时区。理论时区的时间采用其中央经线(或标准经线)的地方时。所以每差一个时区,区时相差一个小时,相差多少个时区,就相差多少个小时。东边的时区时间比西边的时区时间来得早。格林威治的0度经线,向东西各延伸7.5度,构成的15度范围组成的时区就是UTC±0,0时区所采用的时间就是格林威治时间,该时间也被采用为国际标准时间度量。东经7.5-22.5度为东一区,以此类推,西半球也采取相同的类推方式。东十二区和西十二区是重合的(172.5E - 172.5W),国际日期变更线(180E/W)从中间穿越。从东向西穿越,日期加1天,西向东穿越,日期减1天。

法定时区

但是,国界线可不像经线纬线那样直。为了避开国界线,有的时区的形状并不规则,而且比较大的国家以国家内部行政分界线为时区界线,这是实际时区,即法定时区。于是,理论时区匀称、完美的划分,就变成了这样:(图片来自维基百科)

从图中可以看到,中国横跨了5个理论时区(从东五区 - 东九区),但是全部归在了法定时区UTC+8。美国的法定时区则尽量趋近于理论时区,因此就有了美东、美西、太平洋..等时间的区别。为了充分利用阳光,有的地区夏季会采用夏时制。我国曾采用了6年夏时制,但是由于我国将多个理论时区统一为东八区,因此新疆等天亮的较晚的地区并不能起到节约能源的作用,加上我国民众科学素养普遍不高,导致了更多的混乱。因此草草收场。

北京时间

某一国采用哪一个法定时区,一般取决于首都所在的理论时区。北京位于东八区,因此采用东八区中心经线(120E)所在位置的地方平太阳时(理论时间)作为法定时间,而不是北京的地方平太阳时(北京大致位于116E,40W附近)。

移动设备、计算机的时间是如何校准的?

众所周知,目前全球有为数众多的互联网授时服务,例如美国海军天文台授时中心,我国有中国科学院国家授时中心。这些授时服务提供的数据格式多种多样,比如从1970年1月1日到现在多少秒的整数,再比如时间的浮点格式,但是时间基准是GMT,即格林威治国际标准时间。我们电脑全新安装系统,或者手机、平板第一次启用,一般会有区域设置:“UTC+8,北京、香港、台北、新加坡”。这样设备就可以换算出当地时间。

GPS时间

到这里相信很多人也都明白了。GPS模块(以Android手机为例,调用location.getTime())获取的时间,是基于理论时区进行计算的当地理论时间。GPS卫星会广播当前的世界标准时间,然后根据经纬度算出所在理论时区,即可在线性时间内算出理论时区的当地时间。比如你人在新疆喀什,位于理论东五区,此时北京时间是上午10点,那么你的手机时间也是10点,但是GPS获取的时间则是7点(东八区 - 东五区 = 3小时时差)。

仅通过经纬度能否获取当地法定时间?

理论上可行。但是实际上非常困难:由于国界线的不规则性,要存储地球上某一点(假设是10米 * 10米面积的粒度)所在的国家或法定时区,数据量是非常庞大的,实际意义并不大。因此当前的解决方案,都是要求用户自己手动设置区域选项(而且大多是在初始化向导中强制设置)。夏时制的映射规则则要简单多了,因此一般都会有设备自行判断。

“道路寻宝”BUG的解决方案

第一,将时间获取方式改为通过GPS获取,就可以进行真正的日出日落判断。如果以时区为粒度,理论上早晨6点日出,18点日落,这个时刻也是当地理论时间。

第二,有些Android手机厂商开发的driver实在是太烂了,通过getTime可能获取不到当地理论时间,那么只有通过GPS读取的经度进行代码switch-case条件判断了:

switch(longitude)

{

  case 67.5E-82.5E(理论东五区): 使用当地理论时间即“手机时间(北京时间)- 3小时”判断;

  case 82.5E-97.5E(理论东六区): 使用当地理论时间即“手机时间(北京时间)- 2小时”判断;

  .....;

  case 127.5E-142.5E(理论东九区): 使用当地理论时间即“手机时间(北京时间)+ 1小时”判断;// 黑龙江佳木斯市抚远县黑瞎子岛差不多就在134E,这里是中国最东端

}

第三,更好的做法,就是直接通过GPS经纬度,计算该点的日出日落时刻。因为该方式是精确到点的,因此误差只有几秒,而“6点日出18点日落”,误差在半小时以内。这需要复杂的科学计算,用代码库可以实现。

更多

地图应用背后的原理远不止这些。天朝特有的坐标扭曲和偏移也是一大问题,同国际标准的WGS84坐标系相比,国内地图商要交费使用保密的转换插件。

时间: 2024-10-13 16:12:36

时区之痒 - 从手机GPS模块获取的时间,真的是北京时间么?的相关文章

实时获取网络时间 并转换为北京时间的函数

unit Unit1; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs,Winapi.msxml, System.DateUtils, Vcl.StdCtrls; type TForm1 = class(TForm) Button1: TButton

Nodejs 获取北京时间

服务器部署在美国,时区不同.需要把系统时间转换成北京时间. 用 china-time 即可 npm i --save china-time 使用 const chinaTime = require('china-time'); console.log(chinaTime()); // 2018-02-07T04:38:00.000Z console.log(chinaTime().getTime()); // 1517978280000 console.log(chinaTime('YYYY-M

树莓派连接GPS模块

一月份的时候觉得好玩买了树莓派,但是太懒没怎么研究,但最近当初买树莓派时的那个梦想又萦绕心头,决定抽空完成一下当年的计划~ GPS模块是其中很重要的一环,于是在某宝上搜索,找了一家相对便宜也很轻巧的GPS模块,而且这个模块和天线是合体的,非常省空间. 几天后快递来啦,今天有空来鼓捣一下 o(^▽^)o 先来看看这个模块,这是天线的一面 这是组装好之后的效果 我给树莓派安装的是 Raspbian,基于Debian:像 Pidora 的话应该大同小异吧,以下操作均为 Raspbian. 下面来简述一

ionic cordova 引用百度地图以及利用手机GPS定位

首先引入百度地图 在html文件里面加入 <head> <script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=你的密钥"></script> //申请一个百度密钥,建议申请浏览器版的比较方便测试 </head> <body> <button id = "getPosition"&g

fl2440开发板添加GPS模块

1.1 GPS模块与ARM开发板的连接 GPS模块属于字符设备,只需要和FL2440开发的第二个串口连接既可以,然后将GPS测试模块放在室外便可以每隔一段时间向开发板的串口发一个数据包, ~ >: microcom /dev/ttyS1 -s 4800 $GPGGA,024907.000,3029.6642,N,11423.6203,E,1,10,1.0,35.7,M,-13.7,M,,0000*41$GPGSA,A,3,04,08,32,17,28,30,07,11,20,01,,,1.9,1

android Qemu GPS 模块简明分析

Android 的 gps module 是  gps.default.so 在system/lib/hw/ 目录上, 一般提供gps功能的手机应该实现这个module和真实gps硬件交互 Qemu中gps就是要构造一个gps.default.so,  但这个so并不和真的硬件打交道,只是个模拟接口,其代码在sdk/emulator/gps/gps_qemu.c中 Qemu 容器外部实现了一个gps设备,但这个设备和 Android 交互只能通过管道,所以gps_qemu.c的功能就是同管道打交

安卓手机wifi 无法获取ip问题解决

最近买了部安卓的手机,google nexus5 系统是安卓4.4.2. 刚到手就发现链接wifi有问题,一直在获取ip(obtaining ip...)和验证.试过恢复出厂 重启 各种都不管用,只有设置静态ip才可以,但是不能一直这样子呀!! 查了下路由器,路由器已经分配了地址.所以最大可能就是安卓手机上拿到这个地址没有成功写入配置文件,为什么没有写入呢,就是权限的问题了,不明白为什么google会出现这个错误. 因为不熟悉安卓系统,所以查了好几天,终于在一个外国网站上发现了下面这个解决办法,

python:使用netifaces模块获取本机IP网关等信息

python获取本机IP有很多种方法,可每种方法都有局限性. 使用netifaces模块获取本机IP网关等信息,需要安装netifaces模块,不管windows还是linux都可以通用. 一.程序: #!/usr/bin/env python2 # -*- coding: utf-8 -*- #实现本地网卡IP #需要安装netifaces模块 def GetNetworkIP():     #获取本地网卡IP地址     import netifaces     #routingGatewa

GPS模块编程之NMEA0183协议

NMEA 0183是美国国家海洋电子协会(National Marine Electronics Association)为海用电子设备制定的标准格式.现在已经成为GPS导航设备统一的RTCM(Radio Technical Commission for Maritime services)标准协议. 下图是我调试用的GPS芯片,是深圳一家公司生产的.基本上接上天线,供电引脚电压正常的话,就可以通过串口读取GPS数据了.所以GPS编程最主要的是解析数据,要解析数据就得了解协议格式. 下面一组数据