Example of date_time_period boost::locale::period::first_day

Example of date_time_period boost::locale::period::first_day_of_week(int v)

本文关键字:period locale first day of boost time Example date      更新时间:2023-10-16

在boost::locale文档中它说:

date_time_period boost::locale::p eriod::first_day_of_week(int v) [inline]

获取以下方面的date_time_period:一周的第一天,常量,例如美国的星期日 = 1,法国的星期一 = 2

那些返回date_time_period的函数可用于创建自定义boost::locale::date_time对象。

我尝试创建一个std::locale设置为 "en_US.UTF-8" ,因此一周的第一天默认为星期日,然后将其修改为星期一。代码如下:

#include <iostream>
#include <boost/locale.hpp>
int main() {
  using namespace boost::locale;
  date_time_period_set s;
  generator gen;
  std::locale locale = gen("en_US.UTF-8");
  std::locale::global(locale);
  std::cout.imbue(locale);
  s.add(period::year(2000));
  s.add(period::month(6));
  s.add(period::day(5));
  s.add(period::hour(9));
  s.add(period::minute(0));
  s.add(period::second(0));
  s.add(period::first_day_of_week(2));// set the first day of week to Monday
  date_time now(s); // should be 2000-07-05 09:00:00, week starts from Monday
  std::cout << now << std::endl;
}

但是,运行该程序会导致错误:

terminate called after throwing an instance of 'std::invalid_argument'
what():  Invalid date_time period type

错误来自其 ICU 后端适配器:

  static UCalendarDateFields to_icu(period::marks::period_mark f)
  {
      using namespace period::marks;
      switch(f) {
      case era: return UCAL_ERA;
      case year: return UCAL_YEAR;
      case extended_year: return UCAL_EXTENDED_YEAR;
      case month: return UCAL_MONTH;
      case day: return UCAL_DATE;
      case day_of_year: return UCAL_DAY_OF_YEAR;
      case day_of_week: return UCAL_DAY_OF_WEEK;
      case day_of_week_in_month:  return UCAL_DAY_OF_WEEK_IN_MONTH;
      case day_of_week_local: return UCAL_DOW_LOCAL;
      case hour: return UCAL_HOUR_OF_DAY;
      case hour_12: return UCAL_HOUR;
      case am_pm: return UCAL_AM_PM;
      case minute: return UCAL_MINUTE;
      case second: return UCAL_SECOND;
      case week_of_year: return UCAL_WEEK_OF_YEAR;
      case week_of_month: return UCAL_WEEK_OF_MONTH;
      default:
          throw std::invalid_argument("Invalid date_time period type");
      }
  }

first_day_of_week是不可接受的。

所以问题是:

  1. 是否可以使用修改后的"一周的第一天"创建boost::locale::date_time对象?如果属实,该怎么做?
  2. 如何(或在哪里)使用date_time_period boost::locale::period::first_day_of_week(int v)

似乎确实令人困惑。

预赛:

std::locale english = gen("en_US.UTF-8");
std::locale french  = gen("fr_FR.UTF-8");
std::cout.imbue(english); // this one doesn't matter
std::locale::global(french);

经过一些(广泛的)测试,我发现date_time实例上的first_day_of_week值为:

  • 构造时的全局区域设置设置

    std::locale::global(english);
    assert(1 == period::first_day_of_week(date_time()));
    std::locale::global(french);
    assert(2 == period::first_day_of_week(date_time()));
    
  • 或者:从构造期间传递的区域设置中设置

    assert(1 == period::first_day_of_week(date_time(english)));
    assert(2 == period::first_day_of_week(date_time(french)));
    
  • 或者:复制构造期间传递的date_time对象设置(忽略区域设置)

    date_time edt(english), fdt(french);
    assert(1 == period::first_day_of_week(edt));
    edt = date_time(french);
    assert(2 == period::first_day_of_week(edt));
    fdt = date_time(english);
    assert(1 == period::first_day_of_week(fdt));
    
  • 最重要的是:不能从区域设置以外的其他来源设置

    {
        date_time_period_set dtps;
        dtps.add(period::friday());
        dtps.add(period::week_of_year(4));
        // no effect
        dtps.add(period::first_day_of_week(1));
        assert(2 == period::first_day_of_week(date_time(dtps)));
    }
    {
        date_time dt;
        // no effect:
        dt.set(period::first_day_of_week(), 1);
        assert(2 == period::first_day_of_week(dt));
    }
    

无论这是否是一个错误,我都留给开发人员。你也许可以在提升邮件列表中询问它。这确实令人惊讶,因为set接口的存在表明可以更改此属性。

事实上,第一个工作日属性似乎首先不是date_time的属性,而是locale的属性,并且似乎"灌输"在date_time实例上的区域设置不能更改,除非在构造/分配时。

完整测试:Live On Coliru

#include <boost/locale.hpp>
#include <iostream>
int main()
{
    using namespace boost::locale;
    generator gen;
    std::locale english = gen("en_US.UTF-8");
    std::locale french  = gen("fr_FR.UTF-8");
    std::cout.imbue(english); // this one doesn't matter
    std::locale::global(french);
    {
        std::locale::global(english);
        assert(1 == period::first_day_of_week(date_time()));
        std::locale::global(french);
        assert(2 == period::first_day_of_week(date_time()));
    }
    {
        assert(1 == period::first_day_of_week(date_time(english)));
        assert(2 == period::first_day_of_week(date_time(french)));
    }
    {
        date_time_period_set dtps;
        dtps.add(period::friday());
        dtps.add(period::week_of_year(4));
        // no effect
        dtps.add(period::first_day_of_week(1));
        assert(2 == period::first_day_of_week(date_time(dtps)));
    }
    {
        date_time dt;
        // no effect:
        dt.set(period::first_day_of_week(), 1);
        assert(2 == period::first_day_of_week(dt));
    }
    {
        // associated locale gets copied:
        date_time edt(english), fdt(french);
        assert(1 == period::first_day_of_week(edt));
        edt = date_time(french);
        assert(2 == period::first_day_of_week(edt));
        fdt = date_time(english);
        assert(1 == period::first_day_of_week(fdt));
    }
    std::cout << "All tests passedn";
}