【问题标题】:Which boost class should I use to store a human age我应该使用哪个 boost 类来存储人类年龄
【发布时间】:2015-12-16 08:40:41
【问题描述】:

我必须存储用户的年龄(年、月、日......可能是小时、分钟、秒)。我正在使用 C++ 和 boost。

我不确定我应该使用哪一类 boost::posix_time(或 boost::date_time)。

我尝试了boost::posix_time::time_duration,但这并不明显,因为没有构造函数计算一年,只有几个小时,所以我这样做了:

boost::posix_time::time_duration age = boost::posix_time::hours(24*365*ageInYears);

但我不确定这是一个好策略,因为所有年份都没有 365 天 ;-)

我也尝试过boost::gregorian::date,但这很棘手,因为它不允许在 1400 之前存储 year(这会存储日期,而不是持续时间)。

  • 我不想存储用户的出生日期,因为我需要存储程序运行时的年龄(医疗数据)。
  • 我不想存储常规的int,因为它不够准确(24 岁 + 11 个月几乎是 25)。
  • 我不想存储 float,因为我不想通过浮动到年龄的转换重新发明轮子,我必须这样做...

真的没有类可以轻松存储年数和可选的月数和天数吗?

理想情况下,对于一个 30 岁半的人,我希望能够创建这样的对象:boost::....... theAge( 30, 6, 0 );,然后:

  • 具有以年为单位获取年龄的函数:theAge.years() 返回 30(忽略月份)
  • 可能会转换为浮点数,这将使我的年龄达到 30.5 岁

【问题讨论】:

  • "我不想存储用户的出生日期" 所以计算差异 (current_time - date_of_birth) 为boost::posix_time::time_duration。我不认为 1400 是医疗项目的真正限制。
  • 问题是我实际上并不知道患者的出生日期....医生直接输入年龄作为输入。
  • 如果医生输入一个年龄,则计算出生日期。
  • 如果您只有医生输入的年龄,只需使用 age_in_years * 365.25 * 24。无论如何,年龄通常会向下舍入到最接近的年份(或一个月对于非常小的孩子),所以你引入的错误(如果有错误的话)是完全无关紧要的。
  • @jpo38 我知道您明确询问过 boost,但我想指出一个用于日期处理的替代库:howardhinnant.github.io/date_v2.html。根据您的需要,这可能是更好的选择,例如当您必须处理时区或闰秒时(然后与howardhinnant.github.io/tz.html 结合使用)。

标签: c++ boost


【解决方案1】:

boost::posix_time::time_duration 确实是正确执行此操作的一种方法。另一种方法(我个人更喜欢)是同时存储出生日期和“截止日期”,并在需要查找截止日期时减去它们。

在任何情况下,您都不需要花费数年的构造函数 - 您可以简单地从今天减去birth_date - 如果您使用 date_time 对象执行此操作,您将获得 time_duration。

【讨论】:

    【解决方案2】:

    boost::gregorian中确实有持续时间类型,具体来说:

    这些将是存储的理想选择,即存储(年、月、日)的元组。

    请注意,特别是使用 monthsyears 的算术可能会产生意想不到的结果,因为它们提供了快速到月底的行为:

    months single(1); // 1 month duration
    date(2005,Feb,28) + single; // => 2005-Mar-31
    

    来自 OP 所有者的编辑:实际上有一个现有的 boost 结构来存储年/月/日对象 (boost::date_time::date_time::year_month_day_base)。

    这是一个完美回答 OP 的实现:

    class age : public date_time::year_month_day_base<years, months, days>
    {
        typedef date_time::year_month_day_base<years, months, days> baseClass;
    public:
        age( int yearsCount, int monthsCount = 0, int daysCount = 0 ) : 
            baseClass( boost::gregorian::years(yearsCount), 
                       boost::gregorian::months(monthsCount), 
                       boost::gregorian::days(daysCount) )
        {
        }
    
        inline int years() const { return year.number_of_years().as_number(); }
        inline int months() const { return month.number_of_months().as_number(); }
        inline int days() const { return day.days(); }
    
        float getAsFloat() const
        {
            float age = static_cast<float>(years());
            age += months()/12.0f;
            age += days()/365.25f;
            return age;
        }
    };
    

    那么,age(30).years() == 30age(30,6,8).getAsFloat() == 30.521902

    【讨论】:

    • 不幸的是,这与使用boost::gregorian::date 具有相同的限制,因为boost::gregorian::years 拒绝任何值
    • @jpo38 你究竟想如何使用boost::gregorian::years?它应该可以正常工作:coliru.stacked-crooked.com/a/478a0aa295da1c5a
    • 我试过 boost::gregorian::greg_year_month_day patientAge(30,0,0); 这断言是因为年份必须 > 1400 并且因为月份必须是 1..12 并且日必须是 1..31。所以我应该用boost::gregorian::greg_year_month_day patientAge(1430,1,1);来编码一个30岁的年龄……不太方便。
    • @jpo38 我不建议使用boost::gregorian::greg_year_month_day,我建议使用boost::gregorian::yearsboost::gregorian::monthsboost::gregorian::days - 请注意复数。
    • 我在您的帮助下编写的最后一课编辑了您的帖子。谢谢!
    猜你喜欢
    • 2019-01-25
    • 1970-01-01
    • 2011-06-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-27
    • 1970-01-01
    • 2010-12-14
    相关资源
    最近更新 更多