在小数秒内仅用3位数格式化posix时间

时间:2015-01-25 12:58:57

标签: c++ boost time datetime-format time-format

以下代码中的microsec_clock相当于毫秒?

#include <boost/date_time/posix_time/posix_time.hpp>

int main()
{
    boost::posix_time::ptime date_time = boost::posix_time::microsec_clock::local_time();
    const std::string str_time = boost::posix_time::to_simple_string(date_time);
    std::cout << str_time << std::endl;
    return 0;
}
  

输出:2015年1月25日16:26:14.932738

我需要以下输出:

  

输出:2015年1月25日16:26:14.932

2 个答案:

答案 0 :(得分:2)

事实上,这似乎是图书馆的遗漏。

然后,它看起来strftime没有货物:http://en.cppreference.com/w/cpp/chrono/c/strftime

那么,修补time_facet实现以获得此功能需要什么?这是patch反对提升1.57的boost::date_time::time_facet.hppapplied)。

1d0
< 
39a39
>       static const char_type fractional_seconds_3digits[3];              // 3
72a73,76
>   time_formats<CharT>::fractional_seconds_3digits[3] = {'%','3'};
> 
>   template <class CharT>
>   const typename time_formats<CharT>::char_type
215a220
>     static const char_type* fractional_seconds_3digits;               // %3
397a403,411
>       if (local_format.find(fractional_seconds_3digits) != string_type::npos) {
>         // replace %3 with nnn
>         if (frac_str.empty()) {
>           frac_str = fractional_seconds_as_3digit_string(time_arg.time_of_day(), false);
>         }
>         boost::algorithm::replace_all(local_format,
>                                       fractional_seconds_3digits,
>                                       frac_str);
>       }
506a521,529
>       if (format.find(fractional_seconds_3digits) != string_type::npos) {
>         // replace %3 with nnn
>         if (frac_str.empty()) {
>           frac_str = fractional_seconds_as_3digit_string(time_dur_arg, false);
>         }
>         boost::algorithm::replace_all(format,
>                                       fractional_seconds_3digits,
>                                       frac_str);
>       }
550a574,592
>     fractional_seconds_as_3digit_string(const time_duration_type& time_arg,
>                                  bool null_when_zero)
>     {
>       typename time_duration_type::fractional_seconds_type frac_sec =
>         time_arg.fractional_seconds();
> 
>       for (auto n = time_arg.num_fractional_digits(); n>3; --n)
>           frac_sec /= 10;
> 
>       if (null_when_zero && (frac_sec == 0)) {
>         return string_type();
>       }
> 
>       //make sure there is no sign
>       return integral_as_string(date_time::absolute_value(frac_sec), 3);
>     }
> 
>     static
>     string_type
599a642,645
> 
>   template <class time_type, class CharT, class OutItrT>
>   const typename time_facet<time_type, CharT, OutItrT>::char_type*
>   time_facet<time_type, CharT, OutItrT>::fractional_seconds_3digits = time_formats<CharT>::fractional_seconds_3digits;

现在你可以使用Boost DateTime的time_facetptime

#include "time_facet.hpp"
#include <boost/date_time/posix_time/posix_time.hpp>

int main()
{
    using namespace boost::posix_time;
    ptime const date_time = microsec_clock::local_time();

    std::cout << date_time << std::endl;

    auto facet = new time_facet("%Y-%b-%d %H:%M:%S.%f %z");
    std::cout.imbue(std::locale(std::cout.getloc(), facet));
    std::cout << date_time << std::endl;

    facet = new time_facet("%Y-%b-%d %H:%M:%S.%3 %z");
    std::cout.imbue(std::locale(std::cout.getloc(), facet));
    std::cout << date_time << std::endl;
}

打印

2015-Jan-25 22:32:30.392108
2015-Jan-25 22:32:30.392108
2015-Jan-25 22:32:30.392

现在这是一个粗略的补丁,只是为了展示你需要做什么,如果你要添加它。相关的改进似乎是:

  • 支持格式字符串,该字符串允许在小数秒内使用不同数量的数字
  • 使用适当的舍入(而不是截断,现在发生的事情)

我希望这个样本有所帮助。

答案 1 :(得分:0)

这是一种打印字符串的方法,它比修补Boost库(!!)更加容易。关键思想是注意boost::posix_time::to_simple_string()如果精确地为零,则不会打印小数部分。因此,将小数部分设置为零,使用to_simple_string(),然后自己手动打印毫秒。

这引出下一个问题:如何从升压ptime中去除小数部分?我发现的最简单的方法(不一定是存在的最简单的方法!)是使用某个绝对参考点通过time_duration。出于传统考虑,我选择了1970-01-01,但是选择哪个时间点都没有关系(只要它不包含小数秒!)。

std::string time_with_milli(boost::posix_time::ptime time)
{
    using namespace boost::posix_time;
    static const ptime epoch(boost::gregorian::date(1900, 1, 1));  // Can be any date

    boost::posix_time::time_duration relative_time = time - epoch;
    boost::posix_time::ptime date_time_seconds_only = 
        epoch + boost::posix_time::seconds(relative_time.total_seconds());
    uint64_t milliseconds = relative_time.total_milliseconds() % 1000;

    std::stringstream ss;
    ss << to_simple_string(date_time_seconds_only) << '.' 
       << std::setfill('0') << std::setw(3) << milliseconds;
    return ss.str();
}

这与to_simple_string()to_iso_string()to_iso_extended_string()同样有效,即使the documentation for them声称只有to_simple_string()会忽略小数部分(如果为零)。