Skip to content

Boost datetime Examples Translated

Howard Hinnant edited this page Feb 14, 2021 · 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/date.h"
#include <cassert>
#include <iostream>
#include <sstream>
#include <exception>

int
main()
{
    using namespace date;
    using namespace std;
    try
    {
        // The following date is in ISO 8601 extended format (CCYY-MM-DD)
        istringstream in{"2001-10-9"}; // 2001-October-09
        year_month_day d;
        in >> parse("%F", d);
        assert(d.ok());
        cout << format("%Y-%b-%d\n", d);

        // Read ISO Standard(CCYYMMDD) and output ISO Extended
        in.str("20011009"); // 2001-Oct-09
        in >> parse("%Y%m%d", d);
        assert(d.ok());
        cout << d << '\n';  // 2001-10-09

        // Output the parts of the date - Tuesday October 9, 2001
        cout << format("%A %B %e, %Y\n", d);

        // Let's send in month 25 by accident and create an exception
        in.str("20012509"); // 2001-??-09
        in.clear();
        in.exceptions(std::ios::failbit);
        cout << "An expected exception is next:" << endl;
        in >> parse("%Y%m%d", d);
        cout << "oh oh, you shouldn't reach this line:\n";
    }
    catch (const exception& e)
    {
        cout << "Exception: " << e.what() << '\n';
    }
}

Days Alive

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

int
main()
{
    std::string s;
    std::cout << "Enter birth day YYYY-MM-DD (eg: 2002-02-01): ";
    try
    {
        using namespace std::chrono;
        using namespace date;
        std::cin.exceptions(std::ios::failbit);
        local_days d;
        std::cin >> parse("%F", d);
        auto today = make_zoned(current_zone(), system_clock::now());
        auto days_alive = floor<days>(today.get_local_time() - d);
        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\n";
    }
}

Days Between New Years

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

int
main()
{
    using namespace std::chrono;
    using namespace date;
    auto today = floor<days>(make_zoned(current_zone(),
                                        system_clock::now()).get_local_time());
    auto current_year = year_month_day{today}.year();
    auto days_since_year_start = today - local_days{current_year/January/1};
    std::cout << "Days since Jan 1: "
              << days_since_year_start.count() << '\n';
    auto days_until_year_start =
        local_days{(current_year + years{1})/January/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;
    std::cout << "   Enter Year(ex: 2002): ";
    year y;
    std::cin >> parse("%Y", y);
    assert(!std::cin.fail());
    std::cout << "   Enter Month(1..12): ";
    month m;
    std::cin >> parse(" %m", m);
    assert(!std::cin.fail());
    auto start_of_next_year = y/jan + years{1};
    for (auto ym = y/m; ym < start_of_next_year; ym += months{1})
        std::cout << year_month_day{ym/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>

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()
{
    using namespace date;

    std::cout << "Enter Year: ";
    year y;
    std::cin >> parse("%Y", y);

    //define a collection of holidays fixed by month and day
    auto holidays = generate_holidays(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()
{
    using namespace date;
    try
    {
        std::cin.exceptions(std::ios::failbit);
        std::cout << "Enter Year: ";
        year y;
        std::cin >> parse("%Y", y);
        std::cout << "Enter Month(1..12): ";
        month m;
        std::cin >> parse(" %m", m);
        auto ym = y/m;
        auto endOfMonth = (ym/last).day();
        for (auto d = 1_d; d <= endOfMonth; d += days{1})
            std::cout << format("%F [%a]\n", ym/d);
    }
    catch (const std::exception& e)
    {
        std::cerr << "Error bad date, check your entry: \n"
                  << "  Details: " << e.what() << '\n';
    }
}

Month Adding

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

int
main()
{
    using namespace std::chrono;
    using namespace date;
    auto d = year_month_day{floor<days>(make_zoned(current_zone(),
                                        system_clock::now()).get_local_time())};
    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 << " = " << format("%T\n", td);
    // 2002-02-01 00:00:00.000 - 2002-02-01 05:04:02.001 = -05:04:02.001
}

Print Hours

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

int
main()
{
    using namespace std::chrono;
    using namespace date;
    // get the current local time from the clock -- one second resolution
    auto now = make_zoned(current_zone(),
                          floor<seconds>(system_clock::now())).get_local_time();
    // 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';
    std::cout << format("Time left until midnight: %T\n", tomorrow - now);
}

Local to UTC Conversion

#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 = make_zoned(zone, t10);
    std::cout << "UTC <--> Zone base on current setting\n";
    std::cout << t11 << " is " << t10  << " UTC time\n";
    auto td = t11.get_local_time().time_since_epoch() - t10.time_since_epoch();
    std::cout << "A difference of: " << format("%T\n", td);

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

    std::cout << t2.get_sys_time() << " UTC is " << t2.get_local_time() << " New York time\n\n";

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

    std::cout << t5.get_sys_time() << " UTC is " << t5.get_local_time() << " New York time\n\n";

    // Arizona timezone is utc-7 with no dst
    zone = locate_zone("America/Phoenix");
    auto t7 = local_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::literals;
    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/tz.h"
#include <iostream>

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

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

    // local departure time in phoenix is 11 pm on March 30 2005 
    // (ny changes to dst on apr 3 at 2 am)
    zoned_seconds phx_departure{phx_tz, local_days{2005_y/March/30} + 23h};

    // flight is 4 hours, 30 minutes
    zoned_seconds phx_arrival{phx_tz, phx_departure.get_sys_time() + 4h + 30min};
    zoned_seconds nyc_arrival{nyc_tz, phx_arrival};

    std::cout << "departure phx time: " << phx_departure << '\n';
    std::cout << "arrival phx time:   " << phx_arrival << '\n';
    std::cout << "arrival nyc time:   " << nyc_arrival << '\n';
}

// Output:
// 
// departure phx time: 2005-03-30 23:00:00 MST
// arrival phx time:   2005-03-31 03:30:00 MST
// arrival nyc time:   2005-03-31 05:30:00 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 "tz.h"
#include <iostream>

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

    auto nyc_time = make_zoned("America/New_York",
                               local_days(2004_y/oct/4) + 12h + 14min + 32s);
    std::cout << nyc_time << '\n';
    auto sys_epoch = sys_days{};
    std::cout << sys_epoch << '\n';

    // first convert nyc_time to utc via the get_sys_time() 
    // call and subtract the sys_epoch.
    auto sys_time = nyc_time.get_sys_time();

    // Expected 1096906472
    std::cout << "Seconds diff: " << sys_time - sys_epoch << '\n';

    // Take leap seconds into account
    auto utc_time = to_utc_time(sys_time);
    auto utc_epoc = to_utc_time(sys_epoch);

    // Expected 1096906494, an extra 22s
    std::cout << "Seconds diff: " << utc_time - utc_epoc << '\n';
}