What's a good wat to trunctate a time point

Biotronic via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Fri May 5 02:14:21 PDT 2017


On Friday, 5 May 2017 at 08:02:15 UTC, Dukc wrote:
> I have a time point, be it SysTime or DateTime, whatever. I 
> want to trunctate it to weeks, eg. I want it to become the 
> first point of time during the week it was representing. What's 
> a good way to do that? Only hacks came to my mind.
>
> The solution does not have to be generic, trough I'd prefer it 
> to be if it can be without much extra work.

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):

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);
     }
}

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);

     assert(startOfWeek2 == expectedWeek2);
     assert(startOfWeek3 == expectedWeek3);
}


More information about the Digitalmars-d-learn mailing list