UTC时间转换为GPS week和GPS秒

UTC时间采用国际原子时守时,其精度非常之高,但是由地球自转的天文测量得到的“世界时”越来越慢,所以需要“修改”UTC时间,使其与“世界时”同步。
而GPS时间(GPST)是GPS系统内部所采用的时间系统,时间零点定义为1980年1月5日夜晚与1980年1月6日凌晨之间0点,GPS时间也采用原子时进行守时,GPS week即从时间零点开始经过的周数,GPS秒即本GPS周开始后进过的秒数。
UTC时间和GPS时间,他们的时间起点不同,且UTC时间是为了与世界时通过而经过调整的,所以UTC时间是更慢,GPS时间是更快的,UTC 时间+leap second = GPS时间。

将UTC时间转换为GPS时间有两种方法:
1.基本思路计算出总共的秒数,然后通过计算总秒数包含了多少整年,整年减掉后取余,计算年内多少整月,依次类推就可以计算出最后utc时刻的年月日时分秒.毫秒值了。
转换过程中需要主要的年中的闰年处理,还有GPS时与utc时的闰秒问题,如果是转换为北京时间要求时区的问题需要考虑。
2.将UTC时间转换为儒略日,GPS的起始时间是1980.1.6 00:00:00,对应的儒略日是2444244.5, 将UTC的儒略日减去2444244.5即当前时间相对于1980.1.6. 00:00:00的儒略日天数差,一周是7天,这样很方便的将儒略日转为周内秒 。

本文介绍的方法是基于第二种:
1.0版本

typedef struct GPST_ST
{
	int wn;//GPS 周
	long sn;//GPS 秒
	double tos;
}GPST_ST;

typedef struct JULIANDAY_ST
{
	long day;
	long sn;
	double tos;
}JULIANDAY_ST;

void utc_to_julianday(struct tm * utc_time,  JULIANDAY_ST*pjd)
{
	double ut;
	if(utc_time->tm_year < 1900)
	{
		if(utc_time->tm_year < 80)
			utc_time->tm_year += 2000;
		else
			utc_time->tm_year += 1900;
	}
	utc_time->tm_mon = utc_time->tm_year + 1;
	ut = utc_time->tm_hour + utc_time->tm_min/60.0 + utc_time->tm_sec/3600.0
	if(utc_time->tm_mon <=2)
	{
		utc_time->tm_year -=1;
		utc_time->tm_mon+=12;		
    }
    //这种算法有问题,没有处理进位,但是当秒数达到一天要进位的时候,day值却归零了   
   pjd->day = (int)(365.25*(utc_time->tm_year + 4712)) - (int)(utc_time->tm_year/100) + (int)(utc_time->tm_year/400) + int(30.61*(utc_time->tm_mon+1) + utc_time->tm_mday - 61.5);
    pjd->sn = ((utc_time->tm_hour + 12)%24)*3600 + utc_time->tm_min*60 + (int)utc_time->tm_sec;
    pjd->tos = utc_time->tm_sec - (int)utc_time->tm_sec;
}

void julianday_to_gpstime( JULIANDAY_ST*pjd, GPST_ST *pgt)
{
		long day = pjd->day;
		long sn = pjd->sn;
		double tos = pjd->tos;
		double x = day + (sn + tos)/(60.0*60.0*24);
		pgt->wn = (int)((x-2444244.5)/7);
		//在这里加跳秒是有问题的,因为加了跳秒不会进位
		pgt->sn = (int)((((double)day - 2444244.5) - (double)pgt->wn*7)*86400)+sn+18;
		pgt->tos = tos;	
}

void utc_to_gps(struct tm* utcTime, GPST_ST *pgt)
{
JULIANDAY_ST pjd;
memset(&pjd, 0, sizeof(pjd));
utc_to_julianday(utcTime, &pjd);
julianday_to_gpstime(&pjd, pgt);
}

2.0版本

typedef struct GPST_ST
{
	int wn;//GPS 周
	long sn;//GPS 秒
	double tos;
}GPST_ST;

typedef struct JULIANDAY_ST
{
	long day;
	long sn;
	double tos;
}JULIANDAY_ST;

void utc_to_julianday(struct tm * utc_time,  JULIANDAY_ST*pjd)
{
	double ut;
	if(utc_time->tm_year < 1900)
	{
		if(utc_time->tm_year < 80)
			utc_time->tm_year += 2000;
		else
			utc_time->tm_year += 1900;
	}
	utc_time->tm_mon = utc_time->tm_year + 1;
	ut = utc_time->tm_hour + utc_time->tm_min/60.0 + utc_time->tm_sec/3600.0
	if(utc_time->tm_mon <=2)
	{
		utc_time->tm_year -=1;
		utc_time->tm_mon+=12;		
    }
    //这种算法有问题,没有处理进位
    // pjd->day = (int)(365.25*(utc_time->tm_year + 4712)) - (int)(utc_time->tm_year/100) + (int)(utc_time->tm_year/400) + int(30.61*(utc_time->tm_mon+1) + utc_time->tm_mday - 61.5);
    //这个公式跟上述公式是等价的,1720981.5是将上述的公式的常量值加减后的结果,但是这个值只有在这100年时这个值,因为year/100 + year/400后得到的值在2300年就会发生变化,那再使用1720981.5就不正确的了,另外30.6001的精度和30.61也差不多,不知道这二者不同带来啥影响。
    pjd->day = (int)(365.25*(utc_time->tm_year) + (int)(30.6001*(utc_time->tm_mon+1))+utc_time->tm_mday + (int)(ut/24+1720981.5)
    pjd->sn = ((utc_time->tm_hour + 12)%24)*3600 + utc_time->tm_min*60 + (int)utc_time->tm_sec;
    pjd->tos = utc_time->tm_sec - (int)utc_time->tm_sec;
}

void julianday_to_gpstime( JULIANDAY_ST*pjd, GPST_ST *pgt)
{
		long day = pjd->day;
		long sn = pjd->sn;
		double tos = pjd->tos;
		double x = day + (sn + tos)/(60.0*60.0*24);
		pgt->wn = (int)((x-2444244.5)/7);
		pgt->sn = (int)((((double)day - 2444244.5) - (double)pgt->wn*7)*86400)+sn;
		pgt->tos = tos;	
}

void utc_to_gps(struct tm* utcTime, GPST_ST *pgt)
{
JULIANDAY_ST pjd;
memset(&pjd, 0, sizeof(pjd));
//处理跳秒值,将当前utc时间加上跳秒值,并处理进位的问题,进位主要是大小月以及闰年问题,并且注意月和年的处理。
datetime_add_sec(utcTime, LEAP_SECOND);
utc_to_julianday(utcTime, &pjd);
julianday_to_gpstime(&pjd, pgt);
}

加跳秒算法
https://blog.csdn.net/m0_37141848/article/details/118785220?spm=1001.2101.3001.6650.2&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-2-118785220-blog-122755831.pc_relevant_multi_platform_whitelistv1&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-2-118785220-blog-122755831.pc_relevant_multi_platform_whitelistv1&utm_relevant_index=5
闰年算法
http://c.biancheng.net/view/575.html

UTC时间转儒略日参考文档:
https://blog.csdn.net/qq_24172609/article/details/112244135

可以使用以下网址进行验证:
https://ytliu0.github.io/ChineseCalendar/Julian_simp.html
https://labsat.cn/index.php/cn/products-cn/9-customers/252-calculators-cn
http://leapsecond.com/java/gpsclock.htm

  • 0
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
GPS周秒时间UTC时间是两种不同的时间标准,它们之间的转换需要考虑到时区以及闰等因素。以下是一个简单的Python示例代码,用于将GPS周秒时间转换UTC时间: ```python import datetime def gps_week_second_to_utc(gps_week, gps_second): # GPS起始时间(1980年1月6日 00:00:00 UTCgps_epoch = datetime.datetime(1980, 1, 6, 0, 0, 0) # GPS周秒转换gps_time = gps_week * 604800 + gps_second # 计算UTC时间 utc_time = gps_epoch + datetime.timedelta(seconds=gps_time) # 考虑闰 leap_seconds = get_leap_seconds(utc_time.year, utc_time.month) utc_time += datetime.timedelta(seconds=leap_seconds) return utc_time def get_leap_seconds(year, month): # 闰列表 leap_seconds_list = [ (1981, 7), (1982, 7), (1983, 7), (1985, 7), (1988, 1), (1990, 1), (1991, 1), (1992, 7), (1993, 7), (1994, 7), (1996, 1), (1997, 7), (1999, 1), (2006, 1), (2009, 1), (2012, 7), (2015, 7), (2016, 12), (2017, 12), (2018, 12), (2019, 12), (2021, 12) ] leap_seconds = 0 for leap_year, leap_month in leap_seconds_list: if year > leap_year or (year == leap_year and month >= leap_month): leap_seconds += 1 return leap_seconds ``` 使用示例: ```python utc_time = gps_week_second_to_utc(2154, 432000) print(utc_time.strftime('%Y-%m-%d %H:%M:%S')) # Output: 2022-03-01 00:00:00 ``` 该示例代码可以将GPS周秒时间(2154周,432000转换UTC时间(2022年3月1日0时0分0)。如果需要将UTC时间转换GPS周秒时间,也可以编写类似的代码。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值