Re: What's a good wat to trunctate a time point

2017-05-10 Thread Biotronic via Digitalmars-d-learn

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


Re: What's a good wat to trunctate a time point

2017-05-05 Thread Dukc via Digitalmars-d-learn

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


[lots of code]


Wow! You might want to create a pr to phobos from that -It is so 
general, and despite what you say I have seen much worse tested 
stuff there.


Thanks for the reply.


Re: What's a good wat to trunctate a time point

2017-05-05 Thread Biotronic via Digitalmars-d-learn

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


What's a good wat to trunctate a time point

2017-05-05 Thread Dukc via Digitalmars-d-learn
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.