1 /** 2 * Duration parsing 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.parsedur; 15 16 import core.time; 17 18 import std.algorithm.iteration : filter; 19 import std.array; 20 import std.ascii; 21 import std.conv; 22 import std.exception; 23 import std.string; 24 25 /// Parse a duration string in the form returned by Duration.toString 26 /// (e.g. "1 day, 1 hour and 30 minutes") 27 Duration parseDuration(string s) 28 { 29 s = s.replace(" and ", " "); 30 s = s.replace(", ", " "); 31 auto words = std..string.split(s).filter!(word => word.length); 32 enforce(!words.empty, "No duration given"); 33 34 Duration result; 35 36 while (!words.empty) 37 { 38 auto word = words.front; 39 words.popFront(); 40 assert(word.length); 41 enforce(word[0].isDigit || word[0] == '-', "Digit expected: " ~ s); 42 43 auto amount = std.conv.parse!real(word); 44 45 if (!word.length) 46 { 47 if (words.empty) 48 { 49 if (amount == 0) 50 break; 51 throw new Exception("Unit expected"); 52 } 53 word = words.front; 54 words.popFront(); 55 } 56 57 Duration unit; 58 59 word = word.toLower().replace("-", ""); 60 switch (word) 61 { 62 case "nanoseconds": 63 case "nanosecond": 64 case "nsecs": 65 case "nsec": 66 amount /= 100; 67 unit = 1.hnsecs; 68 break; 69 case "hectonanoseconds": 70 case "hectonanosecond": 71 case "hnsecs": 72 case "hns": 73 unit = 1.hnsecs; 74 break; 75 case "microseconds": 76 case "microsecond": 77 case "usecs": 78 case "usec": 79 case "us": 80 case "μsecs": 81 case "μsec": 82 case "μs": 83 unit = 1.usecs; 84 break; 85 case "milliseconds": 86 case "millisecond": 87 case "msecs": 88 case "msec": 89 case "ms": 90 unit = 1.msecs; 91 break; 92 case "seconds": 93 case "second": 94 case "secs": 95 case "sec": 96 case "s": 97 unit = 1.seconds; 98 break; 99 case "minutes": 100 case "minute": 101 case "mins": 102 case "min": 103 case "m": 104 unit = 1.minutes; 105 break; 106 case "hours": 107 case "hour": 108 case "h": 109 unit = 1.hours; 110 break; 111 case "days": 112 case "day": 113 case "d": 114 unit = 1.days; 115 break; 116 case "weeks": 117 case "week": 118 case "w": 119 unit = 1.weeks; 120 break; 121 default: 122 throw new Exception("Unknown unit: " ~ word); 123 } 124 125 result += dur!"hnsecs"(cast(long)(unit.total!"hnsecs" * amount)); 126 } 127 128 return result; 129 } 130 131 /// 132 unittest 133 { 134 assert(parseDuration("1 day, 1 hour and 30 minutes") == 1.days + 1.hours + 30.minutes); 135 assert(parseDuration("0.5 hours") == 30.minutes); 136 assert(parseDuration("0") == Duration.init); 137 }