1 /** 2 * Duration functions. 3 * 4 * License: 5 * This Source Code Form is subject to the terms of 6 * the Mozilla Public License, v. 2.0. If a copy of 7 * the MPL was not distributed with this file, You 8 * can obtain one at http://mozilla.org/MPL/2.0/. 9 * 10 * Authors: 11 * Vladimir Panteleev <ae@cy.md> 12 */ 13 14 module ae.utils.time.fpdur; 15 16 import core.time; 17 18 import ae.utils.time.types : AbsTime; 19 20 /// A variant of core.time.dur which accepts floating-point values. 21 /// Useful for parsing command-line arguments. 22 /// Beware of rounding / floating-point errors! Do not use where precision matters. 23 template dur(string units) 24 if (units == "weeks" || 25 units == "days" || 26 units == "hours" || 27 units == "minutes" || 28 units == "seconds" || 29 units == "msecs" || 30 units == "usecs" || 31 units == "hnsecs" || 32 units == "nsecs") 33 { 34 Duration dur(T)(T length) @safe pure nothrow @nogc 35 if (is(T : real) && !is(T : ulong)) 36 { 37 auto hnsecs = length * convert!(units, "hnsecs")(1); 38 // https://issues.dlang.org/show_bug.cgi?id=15900 39 static import core.time; 40 return core.time.hnsecs(cast(long)hnsecs); 41 } 42 } 43 44 alias weeks = dur!"weeks"; /// Ditto 45 alias days = dur!"days"; /// Ditto 46 alias hours = dur!"hours"; /// Ditto 47 alias minutes = dur!"minutes"; /// Ditto 48 alias seconds = dur!"seconds"; /// Ditto 49 alias msecs = dur!"msecs"; /// Ditto 50 alias usecs = dur!"usecs"; /// Ditto 51 alias hnsecs = dur!"hnsecs"; /// Ditto 52 alias nsecs = dur!"nsecs"; /// Ditto 53 54 /// 55 debug(ae_unittest) unittest 56 { 57 import core.time : msecs; 58 static assert(1.5.seconds == 1500.msecs); 59 } 60 61 /// Multiply a duration by a floating-point number. 62 Duration durScale(F)(Duration d, F f) 63 if (is(F : real)) 64 { 65 return hnsecs(d.total!"hnsecs" * f); 66 } 67 68 /// 69 debug(ae_unittest) unittest 70 { 71 import core.time : seconds, msecs; 72 assert(durScale(1.seconds, 1.5) == 1500.msecs); 73 } 74 75 /// Like d.total!units, but returns fractional parts as well. 76 T fracTotal(string units, T = real)(Duration d) 77 { 78 return T(d.total!"hnsecs") / convert!(units, "hnsecs")(1); 79 } 80 81 /// 82 debug(ae_unittest) unittest 83 { 84 import core.time : seconds, msecs; 85 assert(1500.msecs.fracTotal!"seconds" == 1.5); 86 } 87 88 AbsTime fromUnixTime(double unixTime) 89 { 90 import std.datetime.systime : SysTime; 91 import std.datetime.timezone : UTC; 92 93 auto durationSinceUnixEpoch = unixTime.seconds; 94 enum stdTimeEpoch = SysTime.fromUnixTime(0, UTC()).stdTime; 95 return AbsTime(stdTimeEpoch) + durationSinceUnixEpoch; 96 }