преобразование даты и времени в другой часовой пояс в C ++ / boost - PullRequest
3 голосов
/ 18 января 2012

У меня есть данные о ценах на фондовом рынке Индии, но отметка времени и даты на нем GMT, поэтому я могу работать с данными, представляющими правильную дату и время.

Мне нужно преобразовать датуи время для некоторых записей в моей БД в IST из GMT, моего текущего часового пояса.

mysql> desc price_hist;
+---------------+-----------------------+------+-----+---------+----------------+
| Field         | Type                  | Null | Key | Default | Extra          |
+---------------+-----------------------+------+-----+---------+----------------+
| trade_id      | int(11)               | NO   | PRI | NULL    | auto_increment |
| contract_name | varchar(14)           | NO   | MUL | NULL    |                |
| trade_date    | date                  | NO   |     | NULL    |                |
| trade_time    | varchar(6)            | NO   |     | NULL    |                |
| trade_price   | decimal(10,4)         | NO   |     | NULL    |                |
| trade_volume  | bigint(20)            | NO   |     | NULL    |                |
+---------------+-----------------------+------+-----+---------+----------------+
8 rows in set (0.02 sec)

Я попытался изменить часовой пояс в самой БД, запустив, но это не сработало:

select convert_tz("2010-06-30 19:00:00",'GMT','IST');
+-----------------------------------------------+
| convert_tz("2011-06-30 09:00:00",'GMT','IST') |
+-----------------------------------------------+
| NULL |
+-----------------------------------------------+
1 row in set (0.01 sec) 

Я новичок в Boost, но мне предложили использовать дату Boost для обработки этого в самом коде.

Я искал в некоторых постах преобразование даты и времени, но не нашелсообщение, которое ответило бы на мой конкретный вопрос.

Если есть конкретная ссылка или, что еще лучше, пример буст-кода, которым кто-то может поделиться, это было бы отличным началом для nubee, как я.: -)

Я использовал предоставленную ссылку @Karison, чтобы написать следующий код:

#include "boost/date_time/local_time/local_time.hpp"
  #include <iostream>

  int  main() 
  {
    using namespace boost::posix_time;
    using namespace boost::gregorian;
    using namespace boost::local_time;

    tz_database tz_db;
    time_zone_ptr chi_tz=tz_db.time_zone_from_region("America/Chicago");
    time_zone_ptr jst_tz(new posix_time_zone("EST+5:00:00"));


    local_date_time jpn_time(date(2012,Jan,3), hours(16), jst_tz,local_date_time::NOT_DATE_TIME_ON_ERROR);
    local_date_time osaka_time = jpn_time.local_time_in(chi_tz);
    std::cout<<"osaka_time: "<<osaka_time<<std::endl;
return 0;
}

Ответы [ 2 ]

2 голосов
/ 19 января 2012

Для начала давайте изменим синтаксис и разделим вопросы, как я вижу, их 3.

Первый синтаксис convert_tz принимает строку, которая должна выглядеть как вызов:

select convert_tz('2011-06-30 09:00:00','GMT','IST')

Одиночные галочки, а не двойные кавычки.

Во-вторых. Если ваша машина находится в том же часовом поясе, и вы работаете в POSIX-совместимой системе, вы можете получить строку, представляющую дату, и выполнить:

struct tm result;
strptime(<time string>, <format string>, &result);
time_t epoch_time = mktime(&result);

, который даст вам стандартное время UNIX, которое вы затем сможете использовать, чтобы сделать все, что вам нужно.

Последнее, но не менее важное Повышение. Конечно, это мощная библиотека, но я не думаю, что для проекта вам нужно добавить сложность в это время. Если вы все еще испытываете желание попробовать его или не используете POSIX-совместимую систему, вы можете взглянуть на http://www.boost.org/doc/libs/1_48_0/doc/html/date_time.html,, который вам все равно потребуется для создания ptime из строки, которую вы возвращаете из базы данных, а затем манипулировать это, как вы считаете нужным. Используя часть local_time, создайте объекты часового пояса так, как вам нужно, и затем проверьте время, которое вы получаете из базы данных. Вы можете посмотреть примеры в http://www.boost.org/doc/libs/1_48_0/doc/html/date_time/examples/general_usage_examples.html

Особенно последний. Так что для вашего примера это будет:

time_zone_ptr src_zone(new posix_time_zone("IST+05:30:00"));
time_zone_ptr dst_zone(new posix_time_zone("CST"));
local_date_time trd_time(date(....), hours(...), src_zone, 
                         local_date_time::NOT_DATE_TIME_ON_ERROR);
local_date_time res_time = trd_time.local_time_in(dst_zone);

Не могу гарантировать, что это будет на 100% правильно, но вы поняли идею.

* +1025 * Пример:
#include "boost/date_time/local_time/local_time.hpp"
#include <iostream>

int  main() 
{
    using namespace boost::posix_time;
    using namespace boost::gregorian;
    using namespace boost::local_time;

    tz_database tz_db;
    time_zone_ptr chi_tz(new posix_time_zone("CST-06:00:00");
    time_zone_ptr jst_tz(new posix_time_zone("JST+09:00:00"));

    local_date_time jpn_time(date(2012,Jan,3), hours(16),
                             chi_tz,local_date_time::NOT_DATE_TIME_ON_ERROR);
    local_date_time osaka_time = jpn_time.local_time_in(jst_tz);
    std::cout<<"osaka_time: "<<osaka_time<<std::endl;
    return 0;
}
0 голосов
/ 14 февраля 2012

Вот несколько способов решения этой проблемы:

1) Windows:

#include "stdafx.h"
#include <windows.h>

#include <iostream>
#include <string>
#include <locale>
#include <time.h>
#include <vector>

#include <boost/date_time/local_time/local_time.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/date_time.hpp>
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/split.hpp>

using namespace boost::posix_time;
using namespace boost::gregorian;
using namespace boost::local_time;

//***********
// U T I L S
//***********

std::string WCHAR2StdString(WCHAR* wchar_buf)
{
    char narrow_buf[260];
    char DefChar = ' ';
    WideCharToMultiByte(CP_ACP,0,wchar_buf,-1, narrow_buf,260,&DefChar, NULL);
    return std::string (narrow_buf);
}

std::string LocalTimeZone(TIME_ZONE_INFORMATION & tzi)
{
    short int tz_bias = tzi.Bias;
    std::string tzName(WCHAR2StdString(tzi.StandardName));

    // Get acronym for X_(Zone) Standard Time: 'X_ST'
    std::vector<std::string> vec;
    boost::split(vec, tzName, boost::is_any_of(" "));
    std::string result;
    for(std::vector<std::string>::iterator i = vec.begin(); i != vec.end(); ++i)
    {
        std::string s = *i;
        char c = s.c_str()[0];
        result += c;
    }
    return result;
}

//**********
// M A I N
//**********

int _tmain(int argc, _TCHAR* argv[])  
{
    using namespace boost::posix_time;
    using namespace boost::gregorian;
    using namespace boost::local_time;

    // Windows Timezone info.
    TIME_ZONE_INFORMATION tzi;
    DWORD res = GetTimeZoneInformation(&tzi);

    // Timezone string
    std::string local_tz_str = LocalTimeZone(tzi);

    // Hour Bias
    std::stringstream ss;
    ss << (abs(tzi.Bias)/60);
    std::string bias_hrs(ss.str());

    // Build string: e.g. CST+08:00:00
    short int sign = 0;
    tzi.Bias > 0 ? sign = -1 : sign = 1;

    // Pad with zeros as necessray
    if(abs(tzi.Bias/60) < 10) bias_hrs = ("0" + bias_hrs);
    bias_hrs += ":00:00";
    (sign > 0) ? (bias_hrs = local_tz_str + "+" + bias_hrs) : (bias_hrs = local_tz_str + "-" + bias_hrs);

    local_tz_str = bias_hrs; // local_tz_str is a better name to continue with

    std::string formatted_tz_desc(bias_hrs);

    // Construct local_date_time and time_zone etc.
    long long ticksFromEpoch = 1329122250168; // !!! (assumed input format) milliseconds from 1970-01-01 00:00:00
    std::time_t tt = static_cast<time_t>(ticksFromEpoch/1000); // (ticksFromEpoch/1000) gives seconds since epoch 
    ptime pt = from_time_t(tt);
    time_zone_ptr zone(new boost::local_time::posix_time_zone(formatted_tz_desc));
    local_date_time locally_adjusted_date_time(pt, zone);

    // Format stringstream: YYYY-Mmm-dd HH:MM:SS
    std::stringstream strm;
    strm.imbue(std::locale(std::cout.getloc(), new local_time_facet("%Y-%m-%d %H:%M:%S")));
    strm << locally_adjusted_date_time;

    // Print adjusted result
    std::cout << strm.str() << std::endl << std::endl; 

    return 0;
  }

Вы можете получить информацию о часовом поясе с помощью стандартных библиотек:

2) Posix:

#include <stdio.h>
#include <time.h>
#include <string>
#include <iostream>
#include <vector>
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/split.hpp>

std::string LocalTimeZone();

int main() {
    std::cout << LocalTimeZone() << std::endl;
    return 0;
}

std::string LocalTimeZone()
{
    time_t  now = time(NULL);
    struct tm tnow = *localtime(&now);
    std::string tz = tnow.tm_zone;

    // Format the struct:
    char    buff[100];
    strftime( buff, sizeof buff, "%a %b %d %Y %T %Z%z", &tnow );

    // Parse the bits you want:
    std::vector<std::string> vec;
    const std::string s(buff);
    boost::split(vec, s, boost::is_any_of(" "));
    std::vector<std::string>::iterator i = vec.end();

    return *--i;
}

После форматирования строки часового пояса, например CST+08:00:00 Вы можете продолжить с методом повышения, показанным выше.

НТН

...