On Friday, 5 May 2017 at 09:14:21 UTC, Biotronic wrote:
Here's an implementation that supports start of year, month, week, day, hour, minute and second. Works for DateTime and SysTime. Not heavily tested (all tests included):

As the last sentence says, there were holes in the testing, specifically for unsupported units. Updated:

import std.datetime;

DateTime startOf(string unit, DayOfWeek start = DayOfWeek.sun)(DateTime dt) {
    static if (unit == "year") {
        return DateTime(dt.year, 1, 1);
    } else static if (unit == "month") {
        return DateTime(dt.year, dt.month, 1);
    } else static if (unit == "week") {
        auto delta = dt.dayOfWeek - start;
        if (delta < 0) delta += 7;
return DateTime(dt.year, dt.month, dt.day) - dur!"days"(delta);
    } else static if (unit == "day") {
        return DateTime(dt.year, dt.month, dt.day);
    } else static if (unit == "hour") {
        return DateTime(dt.year, dt.month, dt.day, dt.hour);
    } else static if (unit == "minute") {
return DateTime(dt.year, dt.month, dt.day, dt.hour, dt.minute);
    } else static if (unit == "second") {
return DateTime(dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second);
    } else {
static assert(false, "\"" ~ unit ~ "\" is not a valid time unit for startOf().\nPlease use one of \"year\", \"month\", \"week\", \"day\", \"hour\", \"minute\" or \"second\"");
    }
}

SysTime startOf(string unit)(SysTime st) {
    return SysTime(startOf!unit(cast(DateTime)st), st.timezone);
}

unittest {
    auto now            = DateTime(2017, 5,  5, 10, 39, 17);

    auto expectedYear   = DateTime(2017, 1,  1,  0,  0,  0);
    auto expectedMonth  = DateTime(2017, 5,  1,  0,  0,  0);
    auto expectedWeek   = DateTime(2017, 4, 30,  0,  0,  0);
    auto expectedDay    = DateTime(2017, 5,  5,  0,  0,  0);
    auto expectedHour   = DateTime(2017, 5,  5, 10,  0,  0);
    auto expectedMinute = DateTime(2017, 5,  5, 10, 39,  0);
    auto expectedSecond = DateTime(2017, 5,  5, 10, 39, 17);

    auto startOfYear   = now.startOf!"year";
    auto startOfMonth  = now.startOf!"month";
    auto startOfWeek   = now.startOf!"week";
    auto startOfDay    = now.startOf!"day";
    auto startOfHour   = now.startOf!"hour";
    auto startOfMinute = now.startOf!"minute";
    auto startOfSecond = now.startOf!"second";

    assert(expectedYear   == startOfYear);
    assert(expectedMonth  == startOfMonth);
    assert(expectedWeek   == startOfWeek);
    assert(expectedDay    == startOfDay);
    assert(expectedHour   == startOfHour);
    assert(expectedMinute == startOfMinute);
    assert(expectedSecond == startOfSecond);

    now = DateTime(2017, 4, 30, 10, 39, 17);
    auto expectedWeek2  = DateTime(2017, 4, 24,  0,  0,  0);
    auto startOfWeek2   = now.startOf!("week", DayOfWeek.mon);
    auto expectedWeek3  = DateTime(2017, 4, 29,  0,  0,  0);
    auto startOfWeek3   = now.startOf!("week", DayOfWeek.sat);
    auto expectedWeek4  = DateTime(2017, 4, 30,  0,  0,  0);
    auto startOfWeek4   = now.startOf!("week", DayOfWeek.sun);

    assert(startOfWeek2 == expectedWeek2);
    assert(startOfWeek3 == expectedWeek3);
    assert(startOfWeek4 == expectedWeek4);

    assert(!__traits(compiles, now.startOf!"fortnight"));
}

Reply via email to