Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/date/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 将1970年以来的秒数转换为日期,反之亦然_C++_Date_Math - Fatal编程技术网

C++ 将1970年以来的秒数转换为日期,反之亦然

C++ 将1970年以来的秒数转换为日期,反之亦然,c++,date,math,C++,Date,Math,从1970年1月1日00:00开始,我有几秒钟的时间是以纳秒为单位的int64,我正在尝试将其转换为月/日/年/周/日 迭代的方法很容易做到,我已经做到了,但是我想用公式化的方法来做。我在寻找实际的数学。有很多函数可以实现这一点,请参见,即 将其作为第一个参数传递秒数。第二个参数对于本地时间应该为true,对于GMT应该为false。第三个参数是指向保存响应的结构的指针 返回结构包括(从手册页): tm_sec:分钟后的秒数,通常在0到0之间 59,但可以高达60以允许闰秒 tm_min:小时后

从1970年1月1日00:00开始,我有几秒钟的时间是以纳秒为单位的int64,我正在尝试将其转换为月/日/年/周/日


迭代的方法很容易做到,我已经做到了,但是我想用公式化的方法来做。我在寻找实际的数学。

有很多函数可以实现这一点,请参见,即

将其作为第一个参数传递秒数。第二个参数对于本地时间应该为true,对于GMT应该为false。第三个参数是指向保存响应的结构的指针

返回结构包括(从手册页):

tm_sec:分钟后的秒数,通常在0到0之间 59,但可以高达60以允许闰秒

tm_min:小时后的分钟数,范围为0到59

tm_hour:午夜后的小时数,范围为0到23

TMmday:一个月中的一天,范围为1到31

tm_mon:自1月以来的月数,范围为0到11

tm_年:自1900年以来的年数

tm_wday:自星期日起的天数,范围为0到6

tm_yday:自1月1日起的天数,范围为0到365

tm_isdst:指示夏令时是否生效的标志 在描述的时间。如果采用夏令时,则该值为正值 时间是有效的,如果不是,则为零,如果 目前没有这方面的资料


取决于您想要的时间,或者只需阅读

首先,不要将秒存储为浮点。如果需要微秒/纳秒,请分别存储。你需要整数来做这些计算

这取决于您所在的时区(DST规则、闰年、闰秒),但我想说的是,首先得到天数除以86400的整数。然后通过模除以86400,找出剩下的是什么。现在,您可以通过第一个整数将天数除以365,然后从剩余天数中减去闰日数(通过天数除以365的模计算)来计算已经过去了多少年。您还需要从剩余秒数(已计算)中减去闰秒数。如果减法使这些数字降到零以下,那么从下一个最大的面额中减法。然后,您可以使用日历的显式逻辑计算月份的日期。如果您在DST着陆,请确保添加一小时(或DST偏移量为多少)


就我个人而言,我只想使用,因为它可以完成所有这些和更多(可能比您或我在最初几次迭代中犯的错误要少),但我想我会尝试一下您的问题…

单一Unix规范给出了以下公式:

一个近似已过秒数的值 从古至今。协调世界时名称(以术语指定) 秒(tm_秒)、分钟(tm_分钟)、小时(tm_小时)、天(自 一年中的1月1日(tm_yday),日历年减去1900 (tm_year))与自 纪元,根据下面的表达式

如果年份=1970且值为非负值,则 值与根据 C语言表达式,其中tm_sec、tm_min、tm_hour、tm_yday和 tm_年均为整数类型:

tm_sec + tm_min*60 + tm_hour*3600 + tm_yday*86400 +
    (tm_year-70)*31536000 + ((tm_year-69)/4)*86400 -
    ((tm_year-1)/100)*86400 + ((tm_year+299)/400)*86400
一天中的实际时间与当前值之间的关系 自未指定纪元起的秒数

如何更改自历元以来秒的值 将所需关系与当前实际时间对齐 实现定义。从新纪元开始以秒为单位表示, 每一天都应精确计算86400秒

注: 该表达式的最后三个术语为闰年之后的每一年加上一天,从第一个闰年开始 纪元从1973年开始,第一个任期每四年增加一天 第二,从2001年开始,每100年减去一天 从2001年开始,每400年增加一天。这个 公式中的除法为整数除法;也就是说,剩余的 被丢弃,只留下整数商

要使用这个公式,您需要将月和月的日转换为tmyday,这也应该考虑闰年。公式中的其余部分微不足道

试着从中找出如何从秒数返回日期和时间

编辑

我在中实现了一个整数算术转换器

.

此代码有效

用法: uint32获取安全历元(1970年,自历元起的月、日、年、小时、分钟、秒)

例如: timestamp=getSecsSinceEpoch(1970,6,12,(2014-1970),15,29,0)

退货:1402586940

您可以在www.epochconverter.com上进行验证

写这篇文章花了大约20分钟,大部分时间都花在和一个朋友争论我是否应该包括闰秒、纳秒等等

玩得开心

布莱恩·威尔卡特博士

#define DAYSPERWEEK (7)
#define DAYSPERNORMYEAR (365U)
#define DAYSPERLEAPYEAR (366U)

#define SECSPERDAY (86400UL) /* == ( 24 * 60 * 60) */
#define SECSPERHOUR (3600UL) /* == ( 60 * 60) */
#define SECSPERMIN (60UL) /* == ( 60) */

#define LEAPYEAR(year)          (!((year) % 4) && (((year) % 100) || !((year) % 400)))

const int _ytab[2][12] = {
{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};

/****************************************************
* Class:Function    : getSecsSomceEpoch
* Input     : uint16_t epoch date (ie, 1970)
* Input     : uint8 ptr to returned month
* Input     : uint8 ptr to returned day
* Input     : uint8 ptr to returned years since Epoch
* Input     : uint8 ptr to returned hour
* Input     : uint8 ptr to returned minute
* Input     : uint8 ptr to returned seconds
* Output        : uint32_t Seconds between Epoch year and timestamp
* Behavior      :
*
* Converts MM/DD/YY HH:MM:SS to actual seconds since epoch.
* Epoch year is assumed at Jan 1, 00:00:01am.
****************************************************/
uint32_t getSecsSinceEpoch(uint16_t epoch, uint8_t month, uint8_t day, uint8_t years, uint8_t hour, uint8_t minute, uint8_t second)
{
unsigned long secs = 0;
int countleap = 0;
int i;
int dayspermonth;

secs = years * (SECSPERDAY * 365);
for (i = 0; i < (years - 1); i++)
{   
    if (LEAPYEAR((epoch + i)))
      countleap++;
}
secs += (countleap * SECSPERDAY);

secs += second;
secs += (hour * SECSPERHOUR);
secs += (minute * SECSPERMIN);
secs += ((day - 1) * SECSPERDAY);

if (month > 1)
{
    dayspermonth = 0;

    if (LEAPYEAR((epoch + years))) // Only counts when we're on leap day or past it
    {
        if (month > 2)
        {
            dayspermonth = 1;
        } else if (month == 2 && day >= 29) {
            dayspermonth = 1;
        }
    }

    for (i = 0; i < month - 1; i++)
    {   
        secs += (_ytab[dayspermonth][i] * SECSPERDAY);
    }
}

return secs;
}
#定义DAYSPERWEEK(7)
#定义DAYSPERNORMYEAR(365U)
#定义DAYSPERLEAPYEAR(366U)
#定义SECSPERDAY(86400UL)/*==(24*60*60)*/
#定义SECSPERHOUR(3600UL)/*==(60*60)*/
#定义SECSPERMIN(60UL)/*=(60)*/
#定义闰年(年)(!((年)%4)&((年)%100)| |!((年)%400)))
国际常数[2][12]={
{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};
/****************************************************
*类:函数:getSecsSomceEpoch
*输入:uint16_t纪元日期(即1970年)
*输入:返回月份的uint8 ptr
*输入:返回日期的uint8 ptr
*输入:用户界面
#define DAYSPERWEEK (7)
#define DAYSPERNORMYEAR (365U)
#define DAYSPERLEAPYEAR (366U)

#define SECSPERDAY (86400UL) /* == ( 24 * 60 * 60) */
#define SECSPERHOUR (3600UL) /* == ( 60 * 60) */
#define SECSPERMIN (60UL) /* == ( 60) */

#define LEAPYEAR(year)          (!((year) % 4) && (((year) % 100) || !((year) % 400)))

const int _ytab[2][12] = {
{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};

/****************************************************
* Class:Function    : getSecsSomceEpoch
* Input     : uint16_t epoch date (ie, 1970)
* Input     : uint8 ptr to returned month
* Input     : uint8 ptr to returned day
* Input     : uint8 ptr to returned years since Epoch
* Input     : uint8 ptr to returned hour
* Input     : uint8 ptr to returned minute
* Input     : uint8 ptr to returned seconds
* Output        : uint32_t Seconds between Epoch year and timestamp
* Behavior      :
*
* Converts MM/DD/YY HH:MM:SS to actual seconds since epoch.
* Epoch year is assumed at Jan 1, 00:00:01am.
****************************************************/
uint32_t getSecsSinceEpoch(uint16_t epoch, uint8_t month, uint8_t day, uint8_t years, uint8_t hour, uint8_t minute, uint8_t second)
{
unsigned long secs = 0;
int countleap = 0;
int i;
int dayspermonth;

secs = years * (SECSPERDAY * 365);
for (i = 0; i < (years - 1); i++)
{   
    if (LEAPYEAR((epoch + i)))
      countleap++;
}
secs += (countleap * SECSPERDAY);

secs += second;
secs += (hour * SECSPERHOUR);
secs += (minute * SECSPERMIN);
secs += ((day - 1) * SECSPERDAY);

if (month > 1)
{
    dayspermonth = 0;

    if (LEAPYEAR((epoch + years))) // Only counts when we're on leap day or past it
    {
        if (month > 2)
        {
            dayspermonth = 1;
        } else if (month == 2 && day >= 29) {
            dayspermonth = 1;
        }
    }

    for (i = 0; i < month - 1; i++)
    {   
        secs += (_ytab[dayspermonth][i] * SECSPERDAY);
    }
}

return secs;
}
// Returns number of days since civil 1970-01-01.  Negative values indicate
//    days prior to 1970-01-01.
// Preconditions:  y-m-d represents a date in the civil (Gregorian) calendar
//                 m is in [1, 12]
//                 d is in [1, last_day_of_month(y, m)]
//                 y is "approximately" in
//                   [numeric_limits<Int>::min()/366, numeric_limits<Int>::max()/366]
//                 Exact range of validity is:
//                 [civil_from_days(numeric_limits<Int>::min()),
//                  civil_from_days(numeric_limits<Int>::max()-719468)]
template <class Int>
constexpr
Int
days_from_civil(Int y, unsigned m, unsigned d) noexcept
{
    static_assert(std::numeric_limits<unsigned>::digits >= 18,
             "This algorithm has not been ported to a 16 bit unsigned integer");
    static_assert(std::numeric_limits<Int>::digits >= 20,
             "This algorithm has not been ported to a 16 bit signed integer");
    y -= m <= 2;
    const Int era = (y >= 0 ? y : y-399) / 400;
    const unsigned yoe = static_cast<unsigned>(y - era * 400);      // [0, 399]
    const unsigned doy = (153*(m + (m > 2 ? -3 : 9)) + 2)/5 + d-1;  // [0, 365]
    const unsigned doe = yoe * 365 + yoe/4 - yoe/100 + doy;         // [0, 146096]
    return era * 146097 + static_cast<Int>(doe) - 719468;
}
// Returns year/month/day triple in civil calendar
// Preconditions:  z is number of days since 1970-01-01 and is in the range:
//                   [numeric_limits<Int>::min(), numeric_limits<Int>::max()-719468].
template <class Int>
constexpr
std::tuple<Int, unsigned, unsigned>
civil_from_days(Int z) noexcept
{
    static_assert(std::numeric_limits<unsigned>::digits >= 18,
             "This algorithm has not been ported to a 16 bit unsigned integer");
    static_assert(std::numeric_limits<Int>::digits >= 20,
             "This algorithm has not been ported to a 16 bit signed integer");
    z += 719468;
    const Int era = (z >= 0 ? z : z - 146096) / 146097;
    const unsigned doe = static_cast<unsigned>(z - era * 146097);          // [0, 146096]
    const unsigned yoe = (doe - doe/1460 + doe/36524 - doe/146096) / 365;  // [0, 399]
    const Int y = static_cast<Int>(yoe) + era * 400;
    const unsigned doy = doe - (365*yoe + yoe/4 - yoe/100);                // [0, 365]
    const unsigned mp = (5*doy + 2)/153;                                   // [0, 11]
    const unsigned d = doy - (153*mp+2)/5 + 1;                             // [1, 31]
    const unsigned m = mp + (mp < 10 ? 3 : -9);                            // [1, 12]
    return std::tuple<Int, unsigned, unsigned>(y + (m <= 2), m, d);
}
// Returns day of week in civil calendar [0, 6] -> [Sun, Sat]
// Preconditions:  z is number of days since 1970-01-01 and is in the range:
//                   [numeric_limits<Int>::min(), numeric_limits<Int>::max()-4].
template <class Int>
constexpr
unsigned
weekday_from_days(Int z) noexcept
{
    return static_cast<unsigned>(z >= -4 ? (z+4) % 7 : (z+5) % 7 + 6);
}
#include <iostream>

int
main()
{
    int64_t z = days_from_civil(2015LL, 8, 22);
    int64_t ns = z*86400*1000000000;
    std::cout << ns << '\n';
    const char* weekdays[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
    unsigned wd = weekday_from_days(z);
    int64_t y;
    unsigned m, d;
    std::tie(y, m, d) = civil_from_days(ns/86400/1000000000);
    std::cout << y << '-' << m << '-' << d << ' ' << weekdays[wd] << '\n';
}
1440201600000000000
2015-8-22 Sat
#include "date/tz.h"
#include <iostream>

int
main()
{
    using namespace date;
    auto now  = clock_cast<utc_clock>(sys_days{2016_y/September/26});
    auto then = clock_cast<utc_clock>(sys_days{1970_y/January/1});
    std::cout << now - then << '\n';
}
1474848026s
#include "date/date.h"
#include <iostream>

int
main()
{
    using namespace date;
    using namespace std::chrono_literals;
    auto now  = sys_days{2016_y/September/26} + 0s;
    auto then = sys_days{1970_y/January/1};
    std::cout << now - then << '\n';
}
1474848000s
    for (i = 0; i < (years - 1); i++)
    {   
        if (LEAPYEAR((epoch + i)))
        countleap++;
    }
    for (i = 0; i < years; i++)
 {   
   if (LEAPYEAR((epoch + i)))
    countleap++;
 }
static long UnixTime ( int sec, int min, int hour, int day, int month, int year )
{
  // Cumulative days for each previous month of the year
  int[] mdays = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
  // Year is to be relative to the epoch start
  year -= 1970;
  // Compensation of the non-leap years
  int minusYear = 0;
  // Detect potential lead day (February 29th) in this year?
  if ( month >= 3 )
  {
    // Then add this year into "sum of leap days" computation
    year++;
    // Compute one year less in the non-leap years sum
    minusYear = 1;
  }

  return 
    // + Seconds from computed minutes
    60 * (
      // + Minutes from computed hours
      60 * (
        // + Hours from computed days
        24 * (
          // + Day (zero index)
          day - 1
          // + days in previous months (leap day not included)
          + mdays[month - 1]
          // + days for each year divisible by 4 (starting from 1973)
          + ( ( year + 1 ) / 4 )
          // - days for each year divisible by 100 (starting from 2001)
          - ( ( year + 69 ) / 100 )
          // + days for each year divisible by 400 (starting from 2001)
          + ( ( year + 369 ) / 100 / 4 )
          // + days for each year (as all are non-leap years) from 1970 (minus this year if potential leap day taken into account)
          + ( 5 * 73 /*=365*/ ) * ( year - minusYear )
          // + Hours
        ) + hour
        // + Minutes
      ) + min 
      // + Seconds
    ) + sec;
}
uns32 unixTime;

...
  // Test data returning 0xFfFfFfFf UnixTime
  uns8 year = 2106 - 1970;
  uns8 month = 2;
  uns8 day = 7;
  uns8 hour = 6;
  uns8 min = 28;
  uns8 sec = 15;

  // See original C# code below

  //### Compute days
  // ( 5 * 73 /*=365*/ ) * year
  unixTime = year;
  mulUnixTime( 5 );
  mulUnixTime( 73 );

  // if ( month >= 3 ) year++;
  if ( month > 3 )
    year++;

  // if ( year > 130 ) => minus 1 total days ( year-=4 makes a result of the next division by 4 less by 1)
  if ( year > 130 )
    year -= 4;
  // + ( ( year + 1 ) / 4 )
  addUnixTime( ( year + 1 ) / 4 );
  // + mdays[month - 1]
  addUnixTime( daysInMonths( month ) );
  // + day - 1
  addUnixTime( day - 1 );
  //### Compute hours
  // Hours from computed days
  mulUnixTime( 24 );
  // + Hours
  addUnixTime( hour );
  //### Compute minutes
  // Minutes from computed hours 
  mulUnixTime( 60 );
  // + Minutes
  addUnixTime( min );
  //### Compute seconds
  // Seconds from computed minutes
  mulUnixTime( 60 );
  // + Seconds
  addUnixTime( sec );
...

void mulUnixTime( uns8 mul )
{
  unixTime *= mul;
}

void addUnixTime( uns8 add )
{
  unixTime += add;
}

uns8 daysInMonths( uns8 month @ W )
{
  skip( month );
#pragma computedGoto 1
  return 0xFF;// Dummy value for month 0
  return   0; // January
  return  31; // February
  return  59; // ...
  return  90;
  return 120;
  return 151;
  return 181;
  return 212;
  return 243;
  return 273;
  return 304; // ...
  return 334; // December
#pragma computedGoto 0
}


/*
 static long UnixTime ( int sec, int min, int hour, int day, int month, int year )
  {
    // Cumulative days for each previous month of the year
    int[] mdays = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
    // Year is to be relative to the epoch start
    year -= 1970;
    // Compensation of the non-leap years
    int minusYear = 0;
    // Detect potential lead day (February 29th) in this year?
    if ( month >= 3 )
    {
      // Then add this year into "sum of leap days" computation
      year++;
      // Compute one year less in the non-leap years sum
      minusYear = 1;
    }

    return
      // + Seconds from computed minutes
      60 * (
        // + Minutes from computed hours
        60 * (
          // + Hours from computed days
          24L * (
            // + Day (zero index)
            day - 1
            // + days in previous months (leap day not included)
            + mdays[month - 1]
            // + days for each year divisible by 4 (starting from 1973)
            + ( ( year + 1 ) / 4 )
            // - days after year 2000
            - ( ( year > 130 ) ? 1 : 0 )
            // + days for each year (as all are non-leap years) from 1970 (minus this year if potential leap day taken into account)
            + ( 5 * 73 ) * ( year - minusYear )
          // + Hours
          ) + hour
        // + Minutes
        ) + min
      // + Seconds
      ) + sec;
  }
*/