Получите UT C время до начала текущего года в C ++ - PullRequest
0 голосов
/ 28 февраля 2020

Я пытаюсь получить время EPOCH (универсальное время без разницы между регионами) в начале текущего года. Вот что я написал:

    time_t getEpochTimeAtSOY(){
        /* Get the current year */
        time_t currTime = time(NULL);
        struct tm *aTime = localtime(&currTime);
        int currentYear = aTime->tm_year;   // This is (actualCurrentYear - 1900), so 2020 - 1900 = 120

        /* Now find out EPOCH time for start of currentYear */
        struct tm t;
        time_t timeSinceEpoch = 0;
        memset (&t, 0, sizeof(t));  // Initalize to all 0's
        t.tm_year = currentYear;
        t.tm_mday = 1;

        timeSinceEpoch = timegm(&t); // EPOCH time of 1st Jan <currentYear> 00:00

        return (timeSinceEpoch);
    }

Возвращает правильный результат (ie. 1577836800) на x86 или x86_64, но целевая плата (кросс-компилятор) не поддерживает функцию timegm (). Если я использую mktime () вместо timegm (), это приводит к разнице во времени региона. Может кто-нибудь предложить альтернативное портативное решение? Может быть, используя std :: chrono или что-то еще?

Ответы [ 2 ]

3 голосов
/ 28 февраля 2020

Я только что понял, что getEpochTimeFromSOY() предназначен просто для возврата time_t, связанного с первым годом, а не для вычитания между текущим временем и первым годом. Вот что:

std::time_t
getEpochTimeFromSOY()
{
    using namespace date;
    using namespace std::chrono;
    auto currTime = system_clock::now();
    auto y = year_month_day{floor<days>(currTime)}.year();
    return floor<seconds>(sys_days{y/1/1} - sys_days{})/1s;
}

Это очень просто в C ++ 20, и есть библиотека для этого с синтаксисом C ++ 20, которая работает обратно в C ++ 11 (используя chrono ).

Вот синтаксис C ++ 20:

#include <ctime>
#include <chrono>

std::time_t
getEpochTimeFromSOY()
{
    using namespace std::chrono;
    auto currTime = system_clock::now();
    auto y = year_month_day{floor<days>(currTime)}.year();
    return floor<seconds>(currTime - sys_days{y/1/1})/1s;
}

Вот бесплатная библиотека с открытым исходным кодом только для заголовков, которую вы можете использовать до C ++ 20 , и вот синтаксис для его использования:

#include "date/date.h"

#include <ctime>
#include <chrono>

std::time_t
getEpochTimeFromSOY()
{
    using namespace date;
    using namespace std::chrono;
    auto currTime = system_clock::now();
    auto y = year_month_day{floor<days>(currTime)}.year();
    return floor<seconds>(currTime - sys_days{y/1/1})/1s;
}

Т.е. включите date.h и добавьте using namespace date.

Объяснение кода:

  • Получите текущее время как system_clock::time_point.
  • Получите год текущего времени в UT C.
  • Вычтите первое мгновение года (UT C ) от текущего времени, обрежьте его с точностью до секунд и извлеките счет, разделив на 1 секунду.

Синтаксис 1s был введен в C ++ 14. В C ++ 11 вы можете изменить это на seconds{1}. Или вы можете заменить /1s на .count(), чтобы извлечь секунды как целочисленный тип.

Если вы не хотите использовать для этого бесплатную библиотеку с открытым исходным кодом, вы можете взять основные алгоритмы отсюда и кодируйте его самостоятельно.

1 голос
/ 28 февраля 2020

[Примечание: это скорее «мета-ответ дизайна». Ответ Говарда правильный - и я проголосовал за него. ]

Если бы я писал этот код, я бы вместо этого написал две функции getCurrentYear() и epochTimeAtStartOfYear(year y). Каждый из них выполняет одну функцию и может быть объединен для выполнения того, что вы хотите, но они также могут использоваться в других контекстах.

(Предупреждение - непроверенный код)

std::chrono::year
getCurrentYear()
{
    using namespace std::chrono;
    return year_month_day{floor<days>(system_clock::now())}.year();
}

std::time_t
getEpochTimeFromSOY(std::chrono::year y)
{
    using namespace std::chrono;
    return floor<seconds>(sys_days{y/1/1} - sys_days{})/1s;
}

std::time_t getEpochTimeAtSOY()
{
    return getEpochTimeFromSOY(getCurrentYear());
}
...