Форум программистов, компьютерный форум, киберфорум
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
pav1uxa
1846 / 1698 / 644
Регистрация: 23.01.2014
Сообщений: 6,078
Завершенные тесты: 1
#1

Human Time to Unix Timestamp - C++

29.09.2015, 11:23. Просмотров 836. Ответов 5
Метки нет (Все метки)

Запутался с переводом времени
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/* Перевод времени из формата %d.%m.%y %H:%M:%S (UTC)
 * в метку времени Unix Timestamp
 */
std::string dateStr2str(std::string input)
{
    /* Ввожу 25.09.15 08:40:00
     * На выхоже ожидаю 1443170400
     * Вместо этого получаю разницу в -4 или -7 часов
     */
 
    std::string result = "";
    int day, month, year, hour, minute, second;
 
    sscanf(input.c_str(), "%d.%d.%d %d:%d:%d", &day, &month, &year, &hour, &minute, &second);
 
    std::tm dt;
    dt.tm_mday = day;
    dt.tm_mon = month - 1;
    dt.tm_year = year + 2000 - 1900;
    dt.tm_hour = hour;
    dt.tm_min = minute;
    dt.tm_sec = second;
    std::time_t t = std::mktime(&dt);
    // вывожу разницу в часах после mktime
    // результат 1443156000 -4
    std::cout << t << " " << (t - 1443170400) / 60 / 60 << std::endl;
    dt = *std::gmtime(&t);
    t = std::mktime(&dt);
    // вывожу разницу в часах после gmtime
    // результат 144314200 -7
    std::cout << t << " " << (t - 1443170400) / 60 / 60 << std::endl;
 
    result = std::to_string(t);
    return result;
}
Я, конечно, могу вручную добавлять 4 часа, но думаю это не совсем правильно.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
29.09.2015, 11:23
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Human Time to Unix Timestamp (C++):

Unix timestamp замерить время работы программы - C++
Как можно с помощью unix timestamp замерить время работы программы в секундах (с++)?

Преобразование даты в Unix-time - C++
Нужна формула или функция для преобразование даты в Unix-time. Например: На вход дата: Sun Apr 26 00:06:00 2015 На выход...

Как преобразовать время из строки в Unix Time? - C++
Получаю &quot;Sat, 18 Jul 2015 19:56:37 +0300&quot; Знаю что можно strptime или бустом, но какой шаблон для такого времени?

Не могу разобраться с заданием "Создайте класс Time с конструкторами Time(), Time( int hour)......" - C++
/* Создайте класс Time с конструкторами Time(), Time( int hour), Time(int hour, int min), Time( int h, int m, int s) и ...

Compile-time и run-time методы и функции - C++
Добрый день. Есть две функции, которые делают идентичную работу: template&lt;bool leftShift, typename T&gt; T byteShift(T data) { ...

Класс Human - C++
создать класс human состоящий из полей -имя -фамилия -дата рождения -пол -национальность Класс должен иметь скрытую для...

5
DrOffset
7376 / 4453 / 1009
Регистрация: 30.01.2014
Сообщений: 7,304
29.09.2015, 14:29 #2
Цитата Сообщение от pav1uxa Посмотреть сообщение
Запутался с переводом времени
Тут все просто:
mktime
....
This function performs the reverse translation that localtime does.
mktime для времени полученного через gmtime не совсем подходит.
Поэтому тут есть два пути.
Либо переводить все в "локальном" времени, а затем преобразовывать в UTC.
Либо, воспользоваться нестандартной функцией timegm вместо mktime.
0
pav1uxa
1846 / 1698 / 644
Регистрация: 23.01.2014
Сообщений: 6,078
Завершенные тесты: 1
29.09.2015, 15:36  [ТС] #3
Цитата Сообщение от DrOffset Посмотреть сообщение
Либо переводить все в "локальном" времени, а затем преобразовывать в UTC.
Как?
Цитата Сообщение от DrOffset Посмотреть сообщение
Либо, воспользоваться нестандартной функцией timegm вместо mktime.
У меня OS Windows 7: error: 'timegm' was not declared in this scope
Пробовал _mkgmtime, пишет undefined reference to _mkgmtime.
0
DrOffset
7376 / 4453 / 1009
Регистрация: 30.01.2014
Сообщений: 7,304
29.09.2015, 16:13 #4
Цитата Сообщение от pav1uxa Посмотреть сообщение
Как?
Использовать localtime вместо gmtime и сравнивать с значением локального времени.
Например, для моего часового пояса, 25.09.15 08:40:00 - это 1443156000.
Т.е. как-то так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
std::string dateStr2str(std::string input)
{
    std::string result = "";
    int day, month, year, hour, minute, second;
 
    sscanf(input.c_str(), "%d.%d.%d %d:%d:%d", &day, &month, &year, &hour, &minute, &second);
 
    std::tm dt;
    dt.tm_mday = day;
    dt.tm_mon  = month - 1;
    dt.tm_year = year + 2000 - 1900;
    dt.tm_hour = hour;
    dt.tm_min  = minute;
    dt.tm_sec  = second;
 
    std::time_t t = mktime(&dt); // Это "локальное время"
 
    std::tm dt1 = *std::localtime(&t); // это локальное время в tm
    std::tm dt2 = *std::gmtime(&t);    // это UTC в tm
 
    std::time_t loct = mktime(&dt1);
 
    // Текущий часовой пояс
    std::cout << t << " " << (t - loct) / 60 / 60 << std::endl;
 
    // это уже смещенное время в UTC
    t = mktime(&dt2);
    std::cout << t << " " << (t - loct) / 60 / 60 << std::endl;
 
    result = std::to_string(t);
    return result;
}
Цитата Сообщение от pav1uxa Посмотреть сообщение
У меня OS Windows 7: error: 'timegm' was not declared in this scope
Правильно, потому что ОС надо сразу указывать в вопросе
А если серьезно, то функция POSIX, естественно ее нет в вин. В вин, наверняка что-то из win api придется дергать.

Добавлено через 10 минут
pav1uxa, можно еще вычислить разницу (заранее один раз) и корректировать затем время самостоятельно.
C++
1
2
    std::time_t cur  = std::time(nullptr);
    std::time_t diff = std::difftime(std::mktime(std::gmtime(&cur)), cur);
Добавлено через 48 секунд
Кстати, ты ведь знаешь, что функции типа localtime, gmtime не потокобезопасны?

Добавлено через 3 минуты
Вот, кстати, рабочий пример с timegm в *nix окружении.
http://rextester.com/ZXJZS49318
Чтобы тебе не думалось, что я тебя обманывал
2
pav1uxa
1846 / 1698 / 644
Регистрация: 23.01.2014
Сообщений: 6,078
Завершенные тесты: 1
29.09.2015, 20:48  [ТС] #5
Цитата Сообщение от DrOffset Посмотреть сообщение
Вот, кстати, рабочий пример с timegm в *nix окружении.
http://rextester.com/ZXJZS49318
Чтобы тебе не думалось, что я тебя обманывал
даже не думал так думать) да я и сам находил эту функцию, очень много гуглил прежде чем создать тему.
Цитата Сообщение от DrOffset Посмотреть сообщение
Кстати, ты ведь знаешь, что функции типа localtime, gmtime не потокобезопасны?
нет, я в чистом c/c++ вообще мало чего знаю (оказывается). мне вообще не нравится sscanf и конструкция вида
C++
1
2
3
4
5
6
dt.tm_mday = day;
dt.tm_mon = month - 1;
dt.tm_year = year + 2000 - 1900;
dt.tm_hour = hour;
dt.tm_min = minute;
dt.tm_sec = second;
может это проще делается (стандартными библиотеками), или так сойдет?

Цитата Сообщение от DrOffset Посмотреть сообщение
Т.е. как-то так:
Этот код все равно не дает мне желаемого результата. Мне нужно вводить время в UTC (неважно в каком я часовом поясе, всегда считаем что время вводится в UTC) и получать метку timestamp. Для времени 25.09.15 08:40:00 UTC метка должна быть 1443170400. Все это вообще никак не должно быть привязано ни к каким поясам. В каком бы часовом поясе я не ввел бы 25.09.15 08:40:00, результат всегда должен быть одинм - 1443170400.

В этом примере в моем часовом поясе dt1 отличается от нужного результата на 3, а dt2 уходит еще дальше и отличается на 6.

Добавлено через 10 минут
Цитата Сообщение от DrOffset Посмотреть сообщение
std::time_t cur *= std::time(nullptr);
std::time_t diff = std::difftime(std::mktime(std::gmtime(&cur)), cur);
В принципе похоже на правду, если еще поменять местами аргументы у difftime показывает нормальный результат
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
std::string dateStr2str(std::string input)
{
    std::time_t cur  = std::time(nullptr);
    std::time_t diff = std::difftime(cur, std::mktime(std::gmtime(&cur)));
 
    std::string result = "";
    int day, month, year, hour, minute, second;
 
    std::sscanf(input.c_str(), "%d.%d.%d %d:%d:%d", &day, &month, &year, &hour, &minute, &second);
 
    std::tm dt;
    dt.tm_mday = day;
    dt.tm_mon  = month - 1;
    dt.tm_year = year + 2000 - 1900;
    dt.tm_hour = hour;
    dt.tm_min  = minute;
    dt.tm_sec  = second;
 
    std::time_t t = mktime(&dt);
    t += diff;
 
    result = std::to_string(t);
    return result;
}
Все же хотелось бы привести код к более аккуратному виду. Или сойдет?
0
DrOffset
7376 / 4453 / 1009
Регистрация: 30.01.2014
Сообщений: 7,304
30.09.2015, 13:47 #6
Цитата Сообщение от pav1uxa Посмотреть сообщение
Все же хотелось бы привести код к более аккуратному виду. Или сойдет?
По причинам, которые мне сейчас неочевидны, а времени разбираться особо нет, этот код не работает правильно в онлайн компиляторе. Поэтому я условно считаю, что этот вариант некорректный.

Вообще, послушай меня. Последние лет 5 я все больше склоняюсь к мысли, что в определенных ситуациях лучше написать хороший платформозависимый код, чем плохой универсальный.
Поэтому хочу предложить тебе вот такое решение:
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#include <iostream>
#include <ctime>
#include <cstdio>
 
#ifdef _WIN32
#include <windows.h>
 
bool UTCToUnixTimeWin32(SYSTEMTIME const * stime, std::time_t * t)
{
    static SYSTEMTIME const t1970 = {
        1970, 1, 0, 1, 0, 0, 0, 0
    };
 
    FILETIME ftc, fts;
    if(::SystemTimeToFileTime(stime, &ftc)
    && ::SystemTimeToFileTime(&t1970, &fts))
    {
        ULARGE_INTEGER ltc = { { ftc.dwLowDateTime, ftc.dwHighDateTime } };
        ULARGE_INTEGER lts = { { fts.dwLowDateTime, fts.dwHighDateTime } };
        if(ltc.QuadPart >= lts.QuadPart)
        {
            *t = std::time_t( (ltc.QuadPart - lts.QuadPart) / 10000000 );
            return true;
        }
    }
    return false;
}
#endif
 
std::time_t UTCToUnixTime(std::string const & x)
{
    std::time_t tret = -1;
 
    int day,  month,  year;
    int hour, minute, second;
    if(std::sscanf(x.c_str(), "%d.%d.%d %d:%d:%d"
                   , &day, &month, &year
                   , &hour, &minute, &second) == 6)
    {
#ifdef _WIN32
        SYSTEMTIME const stime = {
            year / 100 == 0 ? 2000 + year : year, month, 0, day
          , hour, minute, second, 0
        };
        UTCToUnixTimeWin32(&stime, &tret);
#else
        std::tm dt = {};
        dt.tm_year = (year / 100 == 0 ? 2000 + year : year) - 1900;
        dt.tm_mon  = month - 1;
        dt.tm_mday = day;
        dt.tm_hour = hour;
        dt.tm_min  = minute;
        dt.tm_sec  = second;
 
        tret = ::timegm(&dt);
#endif
    }
    return tret;
}
 
int main()
{
    std::cout << UTCToUnixTime("25.09.15 08:40:00");
}

Запуск на win: http://rextester.com/KCW22877
Запуск на *nix: http://rextester.com/LBFF22059

On scanf в C++11 можно избавиться, там есть вот это: http://en.cppreference.com/w/cpp/io/manip/get_time
Но эта штука еще не везде работает, а там, где работает - работает по-разному, я проверил. Поэтому в примере ее нет.
Кроме того, в POSIX есть вот такая функция - strptime, с помощью которой всю твою задачу можно уложить в две строки.
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
#include <ctime>
 
std::time_t GetTimeInUTC(std::string const & x)
{
    std::tm tm = {};
    ::strptime(x.c_str(), "%d.%m.%y %H:%M:%S", &tm);
    return ::timegm(&tm);    
}
 
int main()
{
    std::cout << GetTimeInUTC("25.09.15 08:40:00");
}

http://rextester.com/COEDK80206
Но на винде работать не будет.
0
30.09.2015, 13:47
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
30.09.2015, 13:47
Привет! Вот еще темы с ответами:

Напишите конструктор для инициализации объекта класса Time, который может использовать текущее время, возвращаемое функцией time (). - C++
Помогите пожалуйста написать программу на С++. Просто скоро курсовую сдавать, а классы мы еще не разобрали и не успеваем. Поэтому не знаю...

Структура Human (хранение, сортировка) - C++
Привет! Сам текст задания звучит так: Реализовать структуру Human, которая должна содержать следующие данные о человеке: возраст, пол,...

Найти ошибку в Class Human - C++
Найдите ошибку: Class Human{ int Age; string Name; public: Human() {} }

Класс human. Ссылка на неразрешенный внешний символ - C++
Есть код программы. Но при компиляции он выдает ошибки: 1&gt;File1.obj : error LNK2019: ссылка на неразрешенный внешний символ &quot;public:...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
6
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru