一个比较简单的算法来实现判断闰年和卫星时间的转换:
头文件:
#ifndef CASIC_AGNSS_AIDINI_H
#define CASIC_AGNSS_AIDINI_H
// 时间结构体(注意:这里是UTC时间!!!与北京时间有8个小时的差距,不要直接使用北京时间!!!)
// 比如北京时间2016.5.8,10:34:23,那么UTC时间应该是2016.5.8,02:34:23
// 比如北京时间2016.5.8,03:34:23,那么UTC时间应该是2016.5.7,19:34:23
typedef struct
{
int <span style="white-space:pre"> </span>valid; // 时间有效标志,1=有效,否则无效
int <span style="white-space:pre"> </span>year;
int <span style="white-space:pre"> </span>month;
int <span style="white-space:pre"> </span>day;
int <span style="white-space:pre"> </span>hour;
int <span style="white-space:pre"> </span>minute;
int <span style="white-space:pre"> </span>second;
float ms;
} DATETIME_STR;
// 辅助信息(位置,时间,频率)
typedef struct
{
double <span style="white-space:pre"> </span>xOrLat, yOrLon, zOrAlt;
double tow;
float df;
float posAcc;
float tAcc;
float fAcc;
unsigned int res;
unsigned short int wn;
unsigned char timeSource;
unsigned char flags;
} AID_INI_STR;
实现文件:
#include <string.h>
#include <stdio.h>
#include <casicAgnssAidIni.h>
/************************************************************
函数名称:isLeapYear
函数功能:闰年判断。判断规则:四年一闰,百年不闰,四百年再闰。
函数输入:year,待判断年份
函数输出:1, 闰年,0,非闰年(平年)
************************************************************/
int isLeapYear(int year)
{
if ((year & 0x3) != 0)
{ // 如果year不是4的倍数,一定是平年
return 0;
}
else if ((year % 400) == 0)
{ // year是400的倍数
return 1;
}
else if ((year % 100) == 0)
{ // year是100的倍数
return 0;
}
else
{ // year是4的倍数
return 1;
}
}
/*************************************************************************
函数名称: gregorian2SvTime
函数功能: 时间格式转换, 需要考虑UTC跳秒修正
输入的时间格式是常规的年月日时分秒格式的时间;
转换后的时间格式是GPS时间格式,用周数和周内时表示,GPS的时间起点是1980.1.6
GPS时间没有闰秒修正,是连续的时间,而常规时间是经过闰秒修正的
2016年的闰秒修正值是17秒
函数输入: pDateTime, 结构体指针,年月日时分秒格式的时间
函数输出: pAidIni, 结构体指针,周数和周内时(或者天数和天内时)时间格式
*************************************************************************/
void gregorian2SvTime(DATETIME_STR *pDateTime, AID_INI_STR *pAidIni)
{
int DayMonthTable[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
int i, dn, wn;
double tod, tow;
// 天内时间
tod = pDateTime->hour * 3600 + pDateTime->minute * 60 + pDateTime->second + pDateTime->ms / 1000.0;
// 参考时间: 1980.1.6
dn = pDateTime->day;
// 年->天
for (i = 1980; i < (pDateTime->year); i++)
{
if (isLeapYear(i))
{
dn += 366;
}
else
{
dn += 365;
}
}
dn -= 6;
// 月->天
if (isLeapYear(pDateTime->year))
{
DayMonthTable[1] = 29;
}
for (i = 1; i < pDateTime->month; i++)
{
dn += DayMonthTable[i-1];
}
// 周数+周内时间
wn = (dn / 7); // 周数
tow = (dn % 7) * 86400 + tod + 17; // 周内时间,闰秒修正
if (tow >= 604800)
{
wn++;
tow -= 604800;
}
pAidIni->wn = wn;
pAidIni->tow = tow;
}