根据自定义数据字段在 C 中创建 Unix 时间戳

问题描述 投票:0回答:2

我想创建一个 Unix 时间戳。我有一个带有 ble 连接的微控制器,我通过 GATT 连接将当前时间发送到它。我收到了几个整数的数据。

这些是年、月、日、小时、分钟和秒。例如:

  • 年 = 2020,月 = 3,日 = 9,时 = 10,分 = 10,秒 = 10。

我想将其转换为 Unix 时间,这样我就可以通过基于中断的计时器每秒递增该值。因此,将这些数据连接在一起形成 Unix 时间的正确方法是什么。我的推测如下:

创建一个足够大的整数值来存储称为 unix 时间的值,并从相应的时间组件(年、月等)中添加等效的秒数。

这些是以秒为单位的值

  • Year_in_seconds = 31,556,952
  • Month_in_seconds = 2,630,000
  • Day_in_seconds = 86,400
  • Hour_in_seconds = 3,600
  • Minute_in_seconds = 60

因此,Unix 时间 =

  • (nYears * Year_in_seconds)+(nMonths * Month_in_seconds)+(nDays * Days_in_seconds)+(nHours * Hour_in_seconds)+(nMinutes * Minute_in_seconds)+(nSeconds * 1)

我的推测有什么不对吗?

我不知道 unix 时间如何处理一个月中的不同天数,因为不同的月份有不同的长度。还有闰年。那么我是否需要另一个查找表或其他东西来使其准确?

或者从我的数据集中获取 unix 时间的正确方法是什么?

c time unix-timestamp data-conversion
2个回答
3
投票

这应该准确到 2100:

unsigned int tounix (int year, int month, int day, int hour, int min, int sec) {
    unsigned int epoch = 0;
    // These are the number of days in the year up to the corresponding month
    static const unsigned int monthdays[] = { 0, 31, 59, 90, 120, 151, 181, 211, 242, 272, 303, 333 };
    epoch = (year-1970)*86400*365u +    // Account the years
            ((year-1968)/4)*86400 +    // leap years
            monthdays[month-1]*86400 + // days in past full month
            (day-1)*86400u + hour*3600 + min*60 + sec; // days, hours, mins, secs

    if (!(year%4)&&month < 3) // Correct 1 day if in leap year before Feb-29
        epoch -= 86400;

    return epoch;
}

输入预计为:

  • 年份:1970 - 2099
  • 月份:1 - 12
  • 天:1 - 31
  • 时、分、秒:像往常一样;)

0
投票

时间戳只不过是从 1970 年 1 月 1 日到任何特定实例的经过时间。

有了这个逻辑,让我们看看实现从日期时间获取时间戳的方法的步骤。

这些是问题本身提到的以秒为单位的值
Day_in_seconds = 86400
Hour_in_seconds = 3600
Minute_in_seconds = 60

1。首先计算你想要秒数的年份的秒数:

int yearInSeconds = (year - 1970)*365*86400 + // assume all year has only 365 day and multiple 365 * 86400(seconds in a day)
                    (year - 1968)/4 * 86400 // now here we are adding 1 day seconds for all the leaps which comes once in every 4 years from the first leap 1972 to till date

要检查闰年你可以参考这个tool.

2。给定月份的秒数计算:

因为一个月可以有以下可能的天数 [28, 30, 31] // 不包括闰年二月。 让我们创建一个累积月份数组,其中包含任何特定月份的完整月份天数

const int daysInMonth[] = { 0, 31, 59, 90, 120, 151, 181, 211, 242, 272, 303, 333 };

seconds for a month = daysInMonth[month-1] * 86400 // daysInMonth[month-1] 给出完整月份的天数并乘以 86400(一天中的秒数)

3。给定日、时、分、秒的秒数计算:

// seconds of given day, hour, minutes and second as totalSeconds
int totalSeconds = day*86400 + hour*3600 + minute*60 + second; // multipling the given data with the above mentioned constants for day, hour and minute.

4。现在让我们处理特殊情况,如果您正在查询闰日。

在第一步中,我们为所有闰年添加了 1 天秒,如果您查询的是闰年且月份在 2 月或之前,这意味着我们没有超过 2 月 29 日。

为此,我们需要从最终结果中减去天数。

if(!(year%4) && month <= 2) {
  result = result - 1*86400;
}

最终代码如下:

int getUnixTimestamp(int year, int month, int day, int hour, int minute, int second) {
    const int daysInMonth[] = {
        0,
        31,
        59,
        90,
        120,
        151,
        181,
        211,
        242,
        272,
        303,
        333
    };
    int unixtime = (year - 1970) * 86400 * 365 +
        ((year - 1968) / 4) * 86400 +
        daysInMonth[month - 1] * 86400 +
        (day - 1) * 86400 +
        hour * 3600 +
        minute * 60 +
        second;
    if (!(year % 4) && month <= 2) {
        unixtime -= 86400;
    }
    return unixtime;
}

此代码将一直有效到 2100 年,有关更多信息或检查时间转换,您可以使用此 tool.

© www.soinside.com 2019 - 2024. All rights reserved.