GPS秒转北京时间(年月日时分秒)+ gps 周、周内秒转gps时间戳(单位秒) C++ 代码
该文本详细介绍了两种GPS时间转换方法及其对应的RTKlib库实现:
GPS秒转北京时间:
- 通过gpstime2bjtime函数将GPS系统时间(秒)转换为北京当地时间(年月日时分秒),并解释了算法逻辑。
- 包括对闰年的处理方法(每四年一次闰年),以及如何通过循环计算当前日期和时间段。
GPS周及周内秒转GPS时间戳:- 通过readGNSSdata和main函数将原始数据中的周内秒转换为总 GPS 时间戳。
- 展示了如何读取数据并进行时间戳计算,并将其写入输出文件。
该内容适合对RTK定位系统开发人员参考使用。
目录
一、GPS秒转北京时间(年月日时分秒)- 代码如下:
二、gps 周、周内秒转gps时间戳(单位秒)- 代码如下:
在RTKlib中存在一个 time2epoch 方法, 根据官方文档说明该方法用于将gtype_t类型的结构转换为日/时格式的时间戳.
一、GPS秒转北京时间(年月日时分秒)- 代码如下:
void gpstime2bjtime(double gps_time, double *ep)
{
// 分离整数和小数
int gps_t;
double gps_sec;
gps_t = (int)gps_time;
gps_sec = gps_time - gps_t;
const int mday[] = { /* # of days in a month */
31,28,31,30,31,30,31,31,30,31,30,31,31,28,31,30,31,30,31,31,30,31,30,31,
31,29,31,30,31,30,31,31,30,31,30,31,31,28,31,30,31,30,31,31,30,31,30,31};
int days, sec, mon, day;
/* leap year if year%4==0 in 1901-2099 */
days = (int)(gps_t / 86400);
sec = (int)(gps_t - (time_t)days*86400) + 8*60*60 - 18; // UTC转北京时间:北京多了8个时区间( 8*60*60 ),闰了18秒
for (day=days%1461, mon=0; mon<48; mon++)
{
if (day >= mday[mon]) day -= mday[mon];
else break;
}
ep[0] = 1970 + days/1461*4 + mon/12;
ep[1] = mon%12 + 1;
ep[2] = day + 1;
ep[3] = sec / 3600;
ep[4] = sec%3600 / 60;
ep[5] = sec%60 + gps_sec;
}
首先, 它构建了一个名为mday的数组, 具体来说共有48个元素, 每个元素代表连续四年的每个月份, 从起始时间点1970年开始计算(即1970-1973)。这里为何设置为四个月呢? 在判断时需要考虑闰年 的影响: 在非世纪年的格里高利历中能被4整除的年份为闰年, 而在世纪year 中则需满足既能被4整除又能被400整除的条件才是leap year. 以时间为背景来看, 从1970年至2023年间仅有一个世纪year 即2000 year , 它同样符合leap year 的标准. 因此, 在判断时我们只需关注是否能被4整除即可.
自1970年起,在mday数组中对应的第三个位置上记录的第一个闰年的二月具有29天这一特征后,则可推断每四年就是一个完整的闰年周期开始。为此定义了四个整型变量days、sec、mon、day:
> days=(int)(t.time/86400);
>
days是天数,即从GPS秒除86400(即一天的24h)取整,即为天数。
> sec=(int)(t.time-(time_t)days*86400);
>
sec是秒数,即天内秒。
> 1. for (day=days%1461,mon=0;mon<48;mon++) {
>
> 2. if (day>=mday[mon]) day-=mday[mon]; else break;
>
> 3. }
>
>
>
mon代表月份数值,在此情境中取值范围为0至47。day为模1461运算后的余数值。值得注意的是,在本系统中,默认情况下将该余数值与mday数组中的各个月份天数进行对比操作。具体来说,则是将当前余数值与mday数组中每个月份对应的天数值依次进行比较:若当前余数值大于或等于该月的实际天数,则减去该月的具体天数,并转而与下一个月进行同样的比较操作;如此反复直至找到一个满足条件的月份(即当前余数值小于当月实际天数),此时确定的时间段即为所求的具体月份。
> 1. ep[0]=1970+days/1461*4+mon/12; //年数
>
> 2. ep[1]=mon%12+1; //月
>
> 3. ep[2]=day+1;//日
>
> 4. ep[3]=sec/3600; //时
>
> 5. ep[4]=sec%3600/60; //分
>
> 6. ep[5]=sec%60+t.sec;//秒
>
>
>
mon由于其取值范围为0至47,在进行模12运算时需要加1。
day的计算基于days这一整天数结果,在这种情况下相当于往后推一天的时间段。
二、gps 周、周内秒转gps时间戳(单位秒)- 代码如下:
> 1. #include <iostream>
>
> 2. #include <iomanip>
>
> 3. #include <fstream>
>
> 4. #include <math.h>
>
> 5. #include <string>
>
> 6. #include<sstream>
>
> 7. #include <stdlib.h>
>
> 8.
>
> 9.
>
> 10.
>
> 11. using namespace std;
>
> 12.
>
> 13.
>
> 14. // 输入文件路径
>
> 15. std::string P_trueweek = "/home/jht/VIns_Code/GNSS_IMU_Cam_EKFTC_me_Beihang/output/P_true.txt";
>
> 16.
>
> 17. // 输出文件路径 (ecef 坐标下的位置)
>
> 18. FILE *P_tru_sec = fopen("/home/jht/VIns_Code/GNSS_IMU_Cam_EKFTC_me_Beihang/output/P_true_sec.txt", "w");
>
> 19.
>
> 20.
>
> 21.
>
> 22. // 读数据函数
>
> 23. std::ifstream csv_truefile(P_trueweek);
>
> 24. std::string line_llh;
>
> 25.
>
> 26. void read_GNSS_data(const std::string &line, double &time,double XYZ[3])
>
> 27. {
>
> 28. std::stringstream lineStream(line);
>
> 29.
>
> 30. std::string dataRecord[4];
>
> 31. std::getline(lineStream, dataRecord[0], ','); // 这里的数据间是 逗号,用','
>
> 32. std::getline(lineStream, dataRecord[1], ',');
>
> 33. std::getline(lineStream, dataRecord[2], ',');
>
> 34. std::getline(lineStream, dataRecord[3], ',');
>
> 35.
>
> 36.
>
> 37. time = std::stod(dataRecord[0]); //时间:s;
>
> 38.
>
> 39. XYZ[0] = std::stod(dataRecord[1]); //原始数据是增量信息
>
> 40. XYZ[1] = std::stod(dataRecord[2]);
>
> 41. XYZ[2] = std::stod(dataRecord[3]);
>
> 42. }
>
> 43.
>
> 44.
>
> 45.
>
> 46.
>
> 47.
>
> 48. int main()
>
> 49. {
>
> 50. double XYZ[3];
>
> 51. const int week = 2255; // 不同的数据,这个周要变
>
> 52. double timeweeks; // 周内秒的时间
>
> 53. double timesec;
>
> 54.
>
> 55.
>
> 56. while(1)
>
> 57. {
>
> 58. std::getline(csv_truefile, line_llh);
>
> 59. read_GNSS_data(line_llh,timeweeks,XYZ);
>
> 60.
>
> 61. timesec = week*7*24*3600 + timeweeks + 315964800.0;
>
> 62.
>
> 63. fprintf(P_tru_sec, "%.5f,%.3f,%.3f,%.3f\n",timesec,XYZ[0],XYZ[1],XYZ[2]);
>
> 64. }
>
> 65.
>
> 66. return 0;
>
> 67. }
>
> 68.
>
> 69.
>
> 70.
>
>
>
感谢
GPS周-周内秒、日历时、UTC转换和逆转换
