1 概述

最近在学习GPS解算算法时需要在GPS时(GPS周和周内秒)和公历日期之间进行转换,于是就整理了一些时间转换的小程序。 本文介绍了GPS时、公历、儒略日(JD)、简化儒略日(MJD)之间的转换函数。

gps2cal 将GPS周和周内秒转换到公历时间
gps2cal1 由公历日期和GPS周内秒计算公历时间
cal2gps 将公历GPS时间转换到GPS周和周内秒
mjd2cal 将简化儒略日转换到公历时间
cal2mjd 将公历时间转换到简化儒略日
jd2cal 从儒略日计算公历时间
cal2jd 将公历时间转换到儒略日
cal2wd 借助MJD,由公历年月日推算星期几,按照格里高利十三世的历法改革去掉1582年10月5日至14日
cal2wd1 由公历年月日推算星期几,按照英国人的做法去掉1752年9月3日至13日
cal2wd2 不借助MJD,由公历年月日推算星期几,去掉1582年10月5日至14日

在MJD基础上推算星期是很简单的,我顺带写出了从公历推算星期的函数cal2wd。 不借助MJD也可以推算星期,例如安竹林同学在《再谈星期的计算》(《程序员》2001年第4期)介绍的方法。本文给出了这个方法的matlab版本cal2wd1。 cal2wd1按照英国人的历法去掉了公历中的公元1752年9月3日至13日。 我又写了cal2wd2函数,这个函数按照格里高利十三世的做法去掉1582年10月5日至14日。

我在2005年写过一篇《时标与历法》,介绍过一些历法的基础知识。 本文假设读者了解该文介绍的一些概念,例如原子时标、UTC、闰秒、儒略历、儒略日、简化儒略日等。

2 GPS周和周内秒

GPS时从1980年1月6日0时开始计时。GPS时的秒长度与UTC一样,采用原子时标。但GPS时是连续的,不调整闰秒。 在GPS数据中,GPS时通常被表示为GPS周和周内秒。例如:

>> gpst=cal2gps([2009 3 13 22 38 10]) gpst =         1522      513490 >> cal=gps2cal(gpst) cal =         2009           3          13          22          38          10 

即2009年3月13日22:38:10对应gps周1522,周内秒513490。 GPS数据为什么要采用周和周内秒的表示方式呢?

因为这样便于存储和处理。GPS系统内部每隔1.5s会产生一个叫作X1历元的定时事件。 系统通过对X1历元计数的方式计时,这种计时方式被称作Z计数。 Z计数有29bit,高10bit是周数,低19bit是周内秒。 一个星期有604800秒,19bit所能表示的最长时间是(2^19-1)*1.5=786430.5秒,够用啦。 GPS卫星和接收机之间通过Z计数传递时间,所以GPS数据文件中会用到GPS周和周内秒。

我在做数据解算时,有时知道观测日期和周内秒,所以写了一个由公历日期和GPS周内秒计算公历时间的函数gps2cal1:

>> cal=gps2cal1([2009 3 13],513490) cal =         2009           3          13          22          38          10 

请注意这3个函数里的公历时间没有调整闰秒。在GPS数据(例如RINEX格式)中,公历时间也不调整闰秒。

3 儒略日和简化儒略日

我在《时标与历法》中介绍过儒略历、儒略日(JD)和简化儒略日(MJD),这里就不再重复。只是简单说明一下公历的不连续性。 公元1582年3月1日,罗马教皇格里高利十三世在颁布格里高利历(即我们现在使用的公历)时,为了消除已经存在的误差,宣布去掉1582年10月5日至14日。 即1582年10月4日的23:59的下一秒是1582年10月15日的00:00。

我们通常对1582年10月15日0时之后的时间使用格里高利历,对1582年10月4日的23:59之前的时间使用儒略历。 这里的儒略历是指屋大维改革过的儒略历,即奥古斯都历。它和格里高利历除了置闰方式不同,其它是完全一样的。 儒略历是4年一闰,400年100闰。公历是400年97闰,扣掉了3个不能被400整除的世纪年。

例如:香港天文台说儒略日“以倒推到公元前4713年1月1日格林尼治平时正午为起算日期”。这里的公元前4713年1月1日就是按照儒略历倒推的日期。 但没有必要特殊说明儒略历。 本文提供的mjd2cal、cal2mjd、jd2cal、cal2jd函数都使用了规则:公元1582年10月4日24:00点之前使用儒略历,公元1582年10月15日00:00点之后使用格里高利历。 下面是一些使用示例:

>> jd2cal(0) ans =        -4713           1           1          12           0           0 >> mjd2cal(0) ans =         1858          11          17           0           0           0 >> cal2jd([1582 10 4 12 0 0]) ans =      2299160 >> cal2jd([1582 10 15 12 0 0]) ans =      2299161 >> cal2mjd([1582 10 4 0 0 0]) ans =      -100841 >> cal2mjd([1582 10 15 0 0 0]) ans =      -100840 

网上有很多介绍闰年的文章会以公元1000年为例,说它不是闰年。事实上,按照1582年10月4日24:00点之前使用儒略历的规则,公元1000年是闰年。 也就是说公元1000年2月29日在历史上是存在的。例如:

>> cal2jd([1000 2 28 12 0 0]) ans =      2086366 >> cal2jd([1000 2 29 12 0 0]) ans =      2086367 >> cal2jd([1000 3 1 12 0 0]) ans =      2086368 

4 星期推算

在MJD的基础上,我们可以很方便地推算星期。函数cal2wd只需要两行代码:

mjd=floor(cal2mjd(cal)); % 2009年3月9日(MJD 54899)是星期一 wd=mod(mjd-54899,7)+1; 

因为在JD或MJD中,1582年10月5日至14日是不存在的。所以1582年10月15日是星期五,1582年10月4日是星期四:

>> cal2wd([1582 10 15]) ans =      5 >> cal2wd([1582 10 4]) ans =      4 

不借助MJD,也可以直接推算星期。安竹林同学在《再谈星期的计算》一文中介绍了一个简单易行的方法。我将其写成matlab函数cal2wd1。 不过在安同学的代码中,1582年10月5日至14日是存在的,1752年9月3日至13日是不存在的,这是怎么回事呢?

事情是这样的。1582年3月1日格里高利十三世颁布格里高利历后,英国人认为从历史上去掉10天是很荒唐的事情,没有接受。 其实更合理的解释是:格里高利历是罗马教皇颁布的,信奉天主教的意大利、波兰、西班牙、葡萄牙都国家都很痛快地接受了。但英国是新教国家,所以不愿意接受。 直到1752年,英国人才决定采用格里高利历,因为这时儒略历又多算了一天,所以英国人从历史上去掉了11天。 在英国人看来,1752年9月2日的次日是1752年9月14日。

在我看来,还是去掉1582年10月5日至14日更常用一些。所以又在cal2wd1基础上写了cal2wd2。 cal2wd2和cal2wd功能相同,区别仅是前者不依赖cal2mjd函数。cal2wd和cal2wd1也就是对1582年10月5日至1752年9月13日的推算结果不同。 它们对其它日期的推算结果都是相同的,例如它们推算的公元1年1月1日都是星期六:

>> cal2wd([1752 9 14]) ans =      4 >> cal2wd1([1752 9 14]) ans =      4 >> cal2wd([1 1 1]) ans =      6 >> cal2wd1([1 1 1]) ans =      6 

5 结束语

本文提到的源代码可以从这里下载。 其中最复杂的cal2jd和jd2cal是根据www.moshier.net上的代码修改得到。 其实我起初只是想写两个转换gps时间的函数。好奇心让我在半夜查阅相关资料,并用本文记录了这些函数的一些背景。

时间转换与星期推算(Matlab版)的更多相关文章

  1. Java 时间转换问题总结

    这几天开发中遇到时间转换出错的问题,特总结如下:   ========================================================================= ...

  2. Python基本时间转换

    时间转换 python中处理时间的时候,最常用的就是字符形式与时间戳之间的转换. 把最基本的转换在这里记下来 string -> timestamp import time import dat ...

  3. unix环境C编程之日期时间转换

    1.理清概念 1.1.日历时间:   含义:国际标准时间1970年1月1日00:00:00以来经过的秒数.   数据类型:time_t.实际上是long的别名. 1.2.tm结构时间:   含义:结构 ...

  4. mysql 时间函数 时间转换函数

    时间函数 Now 获取当前时间 current_timestamp 获取当前时间 localtimestamp 时间转换 UNIX_TIMESTAMP    "2009-09-15 00:0 ...

  5. mysql 日期操作 增减天数、时间转换、时间戳(转)

    转自http://www.cnblogs.com/wenzichiqingwa/archive/2013/03/05/2944485.html http://hi.baidu.com/juntao_l ...

  6. mysql 日期操作 增减天数、时间转换、时间戳(转换)

    http://hi.baidu.com/juntao_li/item/094d78c6ce1aa060f6c95d0b MySQL datediff(date1,date2):两个日期相减 date1 ...

  7. minix中时间转换的实现(asctime.c)

    在minix2.0源代码中,有相当经典的时间转换函数实现(src\ src\ lib\ ansi\ asctime.c),今天我们就来分析一下asctime.c中的源码 首先引入几个相关的头文件: 1 ...

  8. java日期和时间转换字符

    日期和时间转换字符 字符 描述 例子 c 完整的日期和时间 Mon May 04 09:51:52 CDT 2009 F ISO 8601 格式日期 2004-02-09 D U.S. 格式日期 (月 ...

  9. [jquery]将当前时间转换成yyyymmdd格式

    如题: function nowtime(){//将当前时间转换成yyyymmdd格式 var mydate = new Date(); var str = "" + mydate ...

随机推荐

  1. for/in 循环遍历对象的属性

    for/in 语句循环遍历对象的属性. js中获取key得到某对象中相对应的value的方法:obj.key js中根据动态key得到某对象中相对应的value的方法有二: 一.var key = & ...

  2. Zabbix实战-简易教程--排错(持续收集中)

    一.安装错误 1.zabbix 安装故障之无法跳到下一步或点击下一步没反应 执行命令:chownnginx:nginx /var/lib/php/session/ -R   2.proxy上无法采集交 ...

  3. LoadRunner 中实现MD5加密

    最近在用loadrunner做一个压力测试,在编写脚本的时候发现传递参数的时候需要一个sign值,这个值是将参数进行MD5加密生成的,所以下面就说一说怎么对参数进行MD5加密. 1.首先我们需要一个加 ...

  4. 阿里云Centos 7.4 mssql-server

    1.阿里云服务器控制台,开启1433端口(出入方向都要开).自从微软发布linux版本后,控制台常用端口下拉列表也增加了1433. 2.如果你没配置阿里云yum源,可参照配置一下.http://www ...

  5. RequireJS模块化后JS压缩合并

    使用RequireJS模块化后代码被拆分成多个JS文件了,在部署生产环境需要压缩合并,RequireJS提供了一个打包压缩工具r.js来对模块进行合并压缩.r.js非常强大,不但可以压缩js,css, ...

  6. lambdas了解

    Lambdas了解 功能接口的一个极其宝贵的特性是可以使用lambdas实例化它们.以下是一些关于lambdas的例子: 以逗号分隔的输入列表,左边是指定类型的输入,右边是返回的块:          ...

  7. 城乡联谊胡策会糊厕R3

    因为时间关系这把没设计题面,而且居然还出了锅……T_T 信 原题是leetcode WeeklyContest52 的T1(懒得去找url了 随便搞,但是无解输-1 数字统计 原题PE603 记前n个 ...

  8. 江西理工大学南昌校区cool code竞赛

    这次比赛原本就是来打酱油的,想做个签到题就走!一开始不知道1002是签到题,一直死磕1001,WA了四发过了,回头一看Rank,三十名,我靠!看了1001的AC率,在我AC之前只有一个人AC了,当时我 ...

  9. BZOJ:4873: [Shoi2017]寿司餐厅

    4873: [Shoi2017]寿司餐厅 首先很开心在膜你赛的时候做了出来. 看到数据范围,看到不能dp,看到贡献去重后计算,咦,流? 那就容易了,转最大权闭合子图,每个区间建一个点,取了就一定要取他 ...

  10. jquery 和 mui 上拉加载

    jquery: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <m ...