Skip to content

Boost datetime Examples Translated

Howard Hinnant edited this page May 21, 2016 · 44 revisions

This page shows how the boost datetime examples shown here:

http://www.boost.org/doc/libs/1_59_0/doc/html/date_time/examples.html#date_time.examples.time_math

look if ported to this library.

##Contents


###Dates as String

#include "date.h"
#include <cassert>
#include <iostream>
#include <sstream>
#include <stdexcept>

int
main()
{
    using namespace date;
    using namespace std;
    try
    {
        // The following date is in ISO 8601 extended format (CCYY-MM-DD)
        string s("2001-10-9"); // 2001-October-09
        istringstream in(s);
        int y, m, day;
        char dash;
        in >> y >> dash >> m >> dash >> day;
        auto d = year(y)/m/day;
        assert(d.ok());
        cout << d.year() << '-' << d.month() << '-' << d.day() << '\n';

        // Read ISO Standard(CCYYMMDD) and output ISO Extended
        string ud("20011009"); // 2001-Oct-09
        auto d1 = year(stoi(ud.substr(0, 4)))/stoi(ud.substr(4, 2))
                                             /stoi(ud.substr(6, 2));
        assert(d1.ok());
        cout << d1 << '\n';  // 2001-10-09

        // Output the parts of the date - Tuesday October 9, 2001
        auto wd = weekday{d1};
        cout << wd << ' ' << d1.month() << ' '
             << static_cast<unsigned>(d1.day())
             << ", " << d1.year() << '\n'; // Tue Oct 9, 2001

        // Let's send in month 25 by accident and create an exception
        string bad_date("20012509"); // 2001-??-09
        cout << "An expected exception is next:\n";
        auto d2 = year(stoi(bad_date.substr(0, 4)))
                      /stoi(bad_date.substr(4, 2))
                      /stoi(bad_date.substr(6, 2));
        if (!d2.ok())
        {
            ostringstream msg;
            msg << "Invalid date: " << d2;
            throw runtime_error(msg.str());
        }
        cout << "oh oh, you shouldn't reach this line:\n";
    }
    catch (const exception& e)
    {
        cout << "Exception: " << e.what() << '\n';
    }
}

###Days Alive

#include "date.h"
#include "tz.h"
#include <iostream>
#include <sstream>

int
main()
{
    std::string s;
    std::cout << "Enter birth day YYYY-MM-DD (eg: 2002-02-01): ";
    std::cin >> s;
    try
    {
        using namespace std::chrono;
        using namespace date;
        std::istringstream in(s);
        in.exceptions(std::ios::failbit);
        int y, m, day;
        char dash;
        in >> y >> dash >> m >> dash >> day;
        auto d = year(y)/m/day;
        if (!d.ok())
            throw std::exception{};
        auto birthday = local_days{d};
        auto today = floor<days>(current_zone()->to_local(system_clock::now()));
        auto days_alive = today - birthday;
        if (days_alive == days{1})
            std::cout << "Born yesterday, very funny\n";
        else if (days_alive < days{0})
            std::cout << "Not born yet, hmm: " << days_alive.count() 
                      << " days\n";
        else
            std::cout << "Days alive: " << days_alive.count() << '\n';
    }
    catch (...)
    {
        std::cout << "Bad date entered: " << s << '\n';
    }
}

###Days Between New Years

#include "date.h"
#include "tz.h"
#include <iostream>

int
main()
{
    using namespace std::chrono;
    using namespace date;
    auto today = floor<days>(current_zone()->to_local(system_clock::now()));
    auto current_year = year_month_day{today}.year();
    auto days_since_year_start = today - local_days(current_year/jan/1);
    std::cout << "Days since Jan 1: "
              << days_since_year_start.count() << '\n';
    auto days_until_year_start =
        local_days((current_year + years{1})/jan/1) - today;
    std::cout << "Days until next Jan 1: "
              << days_until_year_start.count() << '\n';
}

###Last Day of the Months

#include "date.h"
#include <cassert>
#include <iostream>

int
main()
{
    using namespace date;
    int yi;
    std::cout << "   Enter Year(ex: 2002): ";
    std::cin >> yi;
    auto y = year{yi};
    assert(y.ok());
    unsigned mi;
    std::cout << "   Enter Month(1..12): ";
    std::cin >> mi;
    auto m = month{mi};
    assert(m.ok());
    auto start_of_next_year = y/jan/1 + years{1};
    for (auto d = y/m/1; d < start_of_next_year; d += months{1})
        std::cout << year_month_day{d.year()/d.month()/last} << '\n';
}

###Localization Demonstration

#include "date.h"
#include <iomanip>
#include <iostream>

// Define a series of char arrays for short and long name strings 
// to be associated with German date output (US names will be 
// retrieved from the locale).
const char* const de_long_month_names[] =
{
    "Januar", "Februar", "Marz", "April", "Mai",
    "Juni", "Juli", "August", "September", "Oktober",
    "November", "Dezember", "NichtDerMonat"
};

const char* const de_long_weekday_names[] = 
{
    "Sonntag", "Montag", "Dienstag", "Mittwoch",
    "Donnerstag", "Freitag", "Samstag"
};

int
main()
{
    using namespace date;

    // create some gregorian objects to output
    auto d1 = 2002_y/oct/1;
    auto m = d1.month();
    auto wd = weekday{d1};

    using namespace std;
    // output the date in German using short month names
    cout << d1.day() << '.'
         << setw(2) << static_cast<unsigned>(d1.month())
         << '.' << d1.year() << '\n';
    cout << de_long_month_names[static_cast<unsigned>(m)-1] << '\n';
    cout << de_long_weekday_names[static_cast<unsigned>(wd)] << '\n';
    cout << static_cast<unsigned>(d1.month()) << '/' << d1.day()
         << '/' << d1.year() << '\n';
    cout << d1.year() << '-' << d1.month() << '-' << d1.day() << '\n';
}

If your OS supports the std::locale("de_DE") the above can be simplified to:

#include "date.h"
#include "tz.h"
#include <iostream>

int
main()
{
    using namespace date;

    // create some gregorian objects to output
    auto d1 = 2002_y/oct/1;

    using namespace std;
    locale loc("de_DE");
    cout << format(loc, "%x\n", local_days{d1});
    cout << format(loc, "%B\n", local_days{d1});
    cout << format(loc, "%A\n", local_days{d1});
    cout << format(loc, "%D\n", local_days{d1});
    cout << format(loc, "%F\n", local_days{d1});
}

###Date Period Calculations

#include "date.h"
#include <iostream>
#include <iterator>

int
main()
{
    using namespace date;
    using date_period = std::pair<year_month_day, year_month_day>;
    constexpr date_period ps[] =
    {
        {feb/ 2/2002, feb/ 4/2002},  // weekend of 2nd-3rd
        {feb/ 9/2002, feb/11/2002},
        {feb/16/2002, feb/18/2002},
        {feb/23/2002, feb/25/2002},
        {feb/12/2002, feb/13/2002}   // a random holiday 2-12
    };
    std::cout << "Number Excluded Periods: "  << sizeof(ps)/sizeof(ps[0]) << '\n';
    auto d = feb/16/2002;
    for (const auto& p : ps)
    {
        std::cout << p.first << " / " << p.second << '\n';
        if (p.first <= d && d < p.second)
            std::cout << "In Exclusion Period: "
                      << d << " --> "
                      << p.first << " / " << p.second << '\n';
    }
}

###Print Holidays

#include "date.h"
#include <iostream>
#include <vector>

std::vector<date:: sys_days>
generate_holidays(date::year y)
{
    using namespace date;
    std::vector< sys_days> holidays;
    holidays.push_back(y/jan/1);       // Western New Year
    holidays.push_back(y/jul/4);       // US Independence Day
    holidays.push_back(y/dec/25);      // Christmas day
    holidays.push_back(y/sep/mon[1]);  // US labor day
    holidays.push_back(y/jan/mon[3]);  // MLK Day
    holidays.push_back(y/feb/tue[2]);  // Pres day
    holidays.push_back(y/nov/thu[4]);  // Thanksgiving
    std::sort(holidays.begin(), holidays.end());
    return holidays;
}

int
main()
{

    std::cout << "Enter Year: ";
    int y;
    std::cin >> y;

    using namespace date;
    //define a collection of holidays fixed by month and day
    auto holidays = generate_holidays(year{y});
    for (const auto& d : holidays)
        std::cout << d << " [" << weekday(d) << "]\n";
    std::cout << "Number Holidays: " << holidays.size() << '\n';
}

###Print Month

#include "date.h"
#include <iostream>

int
main()
{
    std::cout << "Enter Year: ";
    int yi, mi;
    std::cin >> yi;
    std::cout << "Enter Month(1..12): ";
    std::cin >> mi;
    try
    {
        using namespace date;
        auto ym = year(yi)/mi;
        if (!ym.ok())
            throw std::runtime_error("Bad year or month: "
                         + std::to_string(yi) + "/" + std::to_string(mi));
        auto wd = weekday{ym/1};
        auto endOfMonth = (ym/last).day();
        for (auto d = 1_d; d <= endOfMonth; d += days{1}, wd += days{1})
            std::cout << ym.year() << '-' << ym.month() << '-'
                      << d << " [" << wd << "]\n";
    }
    catch (const std::exception& e)
    {
        std::cerr << "Error bad date, check your entry: \n"
                  << "  Details: " << e.what() << '\n';
    }
}

###Month Adding

#include "date.h"
#include "tz.h"
#include <iostream>

int
main()
{
    using namespace std::chrono;
    using namespace date;
    auto zone = current_zone();
    auto d = year_month_day{floor<days>(
                              zone->to_local(system_clock::now()))};
    auto d2 = d + months{1};
    if (!d2.ok())
        d2 = d2.year()/d2.month()/last;  // boost snaps to last
    std::cout << "Today is: " << d << ".\n"
              << "One month from today will be: " << d2 << '\n'; 
}

###Time Math

#include "date.h"
#include <iostream>

int
main()
{
    using namespace std::chrono;
    using namespace date;

    auto d = sys_days(2002_y/feb/1);  // an arbitrary date;
    // construct a time by adding up some durations durations
    auto t1 = d + 5h + 4min + 2s + 1ms;
    // construct a new time by subtracting some times
    auto t2 = t1 - 5h - 4min - 2s - 1ms;
    // construct a duration by taking the difference between times
    auto td = t2 - t1;
    std::cout << t2 << " - " << t1 << " = " << make_time(td) << '\n';
    // 2002-02-01 00:00:00.000 - 2002-02-01 05:04:02.001 = -05:04:02.001
}

###Print Hours

#include "date.h"
#include "tz.h"
#include <iostream>

int
main()
{
    using namespace std::chrono;
    using namespace date;
    // get the current time from the clock -- one second resolution
    auto now = floor<seconds>(current_zone()->
                                to_local(system_clock::now()).first);
    // Get the date part out of the time
    auto today = floor<days>(now);
    auto tomorrow = today + days{1};  // midnight
    for (auto i = now; i < tomorrow; i += 1h)
        std::cout << i << '\n';
    auto remaining = tomorrow - now;
    std::cout << "Time left until midnight: " 
              << make_time(remaining) << '\n';
}

###Local to UTC Conversion

#include "date.h"
#include "tz.h"
#include <iostream>

int
main()
{
    using namespace std::chrono;
    using namespace date;
    auto zone = current_zone();
    auto t10 = sys_days(2002_y/jan/1) + 7h;
    auto t11 = zone->to_local(t10);
    std::cout << "UTC <--> Zone base on current setting\n";
    std::cout << t11.first << ' ' << t11.second << " is "
              << t10  << " UTC time\n";
    auto td = t11.first - t10;
    std::cout << "A difference of: " << make_time(td) << '\n';

    // eastern timezone is utc-5
    zone = locate_zone("America/New_York");
    // 5 hours b/f midnight NY time
    auto t1 = sys_days(2001_y/dec/31) + 19h + 0s;
    std::cout << "\nUTC <--> New York while DST is NOT active (5 hours)\n";
    auto t2 = zone->to_sys(t1);
    std::cout << t1 << " in New York is " << t2 << " UTC time\n";

    auto t3 = zone->to_local(t2).first;  // back should be the same
    std::cout << t2 << " UTC is " << t3 << " New York time\n\n";

    // 4 hours b/f midnight NY time
    auto t4 = sys_days(2002_y/may/31) + 20h + 0s;
    std::cout << "UTC <--> New York while DST is active (4 hours)\n";
    auto t5 = zone->to_sys(t4);
    std::cout << t4 << " in New York is " << t5 << " UTC time\n";

    auto t6 = zone->to_local(t5).first;  // back should be the same
    std::cout << t5 << " UTC is " << t6 << " New York time\n\n";

    // Arizona timezone is utc-7 with no dst
    zone = locate_zone("America/Phoenix");
    auto t7 = sys_days(2002_y/may/31) + 17h + 0s;
    std::cout << "UTC <--> Arizona (7 hours)\n";
    auto t8 = zone->to_sys(t7);
    std::cout << t7 << " in Arizona is " << t8 << " UTC time\n";
}

###Time Periods

#include "date.h"
#include <iostream>

int
main()
{
    using namespace std::chrono;
    using namespace date;
    auto d = sys_days(2002_y/feb/1);  // an arbitrary date
    auto t = d + 3h + 5s;              //an arbitray time on that day
    if (d <= t && t < d + days{1})
        std::cout << d << " contains " << t << '\n';
    // Time periods not part of this library but can be built
    //   from a pair of time_points.
}

###Simple Time Zones

The boost example shows custom time zones. This library supports only the full history of the IANA timezone database. To achieve a custom timezone you would need to edit the IANA timezone database. For an example using the IANA timezone database see the Local to UTC Conversion example.

###Daylight Savings Calc Rules

// This library does not support custom daylight savings rules.  But it
// does support the notion of partial dates and finding the nth (or last)
// weekday of a month.

#include "date.h"

int
main()
{
    using namespace date;
    auto fd_start = sun[1]/may;
    auto ld_start = sun[last]/may;
    auto nkd_start = sun[3]/may;
    auto pd_start = may/1;
    auto fd_end = sun[1]/oct;
    auto ld_end = sun[last]/oct;
    auto nkd_end = sun[3]/oct;
    auto pd_end = oct/31;
}

###Flight Time Example

#include "date.h"
#include "tz.h"
#include <iostream>

int
main()
{
    using namespace std::chrono;
    using namespace date;

    // set up some timezones for creating and adjusting local times
    auto nyc_tz = locate_zone("America/New_York");
    auto phx_tz = locate_zone("America/Phoenix");

    // local departure time in phoenix is 11 pm on March 30 2005 
    // (ny changes to dst on apr 3 at 2 am)
    auto phx_departure = sys_days(2005_y/mar/30) + 23h + 0min;
    auto utc_departure = phx_tz->to_sys(phx_departure);

    auto flight_length = 4h + 30min;
    auto utc_arrival = utc_departure + flight_length;

    auto phx_arrival = phx_tz->to_local(utc_arrival);
    auto nyc_arrival = nyc_tz->to_local(utc_arrival);

    std::cout << "departure phx time: " << phx_departure << '\n';
    std::cout << "arrival phx time:   "
              << floor<minutes>(phx_arrival.first)
              << ' ' << phx_arrival.second << '\n';
    std::cout << "arrival nyc time:   "
              << floor<minutes>(nyc_arrival.first)
              << ' ' << nyc_arrival.second << '\n';
}

// Output:
// 
// departure phx time: 2005-03-30 23:00
// arrival phx time:   2005-03-31 03:30 MST
// arrival nyc time:   2005-03-31 05:30 EST
// 
// Note that boost states a nyc_arrival time of 2005-Mar-31 06:30:00 EDT
// because boost uses the current US daylightsavings rules as opposed to
// those that were in effect in 2005.  This library varies its DST rules
// with the date.

###Seconds Since Epoch

#include "date.h"
#include "tz.h"
#include <iostream>

int
main()
{
    using namespace std::chrono;
    using namespace date;

    auto nyc_tz = locate_zone("America/New_York");
    auto nyc_time = sys_days(2004_y/oct/4) + 12h + 14min + 32s;
    std::cout << nyc_time << '\n';
    auto time_t_epoch = sys_days(1970_y/1/1);
    std::cout << time_t_epoch << '\n';

    // first convert nyc_time to utc via the utc_time() 
    // call and subtract the ptime.
    auto sys_time = nyc_tz->to_sys(nyc_time);
    auto diff = sys_time - time_t_epoch;

    // Expected 1096906472
    std::cout << "Seconds diff: " << diff.count() << '\n';

    // Take leap seconds into account
    auto utc_time = utc_clock::sys_to_utc(sys_time);
    auto utc_epoc = utc_clock::sys_to_utc(time_t_epoch);
    diff = utc_time - utc_epoc;

    // Expected 1096906494, an extra 22s
    std::cout << "Seconds diff: " << diff.count() << '\n';
}
Clone this wiki locally