How can I convert a duration in minutes/seconds in google sheets - google-sheets

I have a google sheet column which has the duration column in the format as like the below. 4w 1d 19h 56m 16s. How can I convert this in total minutes/seconds?
PS: Every value in that list will be optional. Meaning, Sometime Weeks will be missing and days will be missing etc.

total minutes/seconds
=ARRAYFORMULA(IF(A1:A10="",,TEXT(MMULT(IFERROR(REGEXEXTRACT(SPLIT(A1:A10, " "), "\d+")*
VLOOKUP(REGEXEXTRACT(SPLIT(A1:A10, " "), "\d+(.*)"),
{"s",1;"m",60;"h",3600;"d",86400;"w",604800}, 2, 0), 0),
SEQUENCE(COLUMNS(SPLIT(A1:A10, " ")), 1, 1, 0))/86400, "[mm]:ss")))

If the column values are simple strings and you're using Apps Script, you may be able to do something like this:
function transformDurationString(dString) {
const multipliers = {
s: 1,
m: 60,
h: 60 * 60,
d: 60 * 60 * 24,
w: 60 * 60 * 24 * 7,
};
let totalSeconds = 0;
let durations = dString.split(" ");
for (const duration of durations) {
const durationValue = Number(duration.slice(0, -1));
const durationType = duration.slice(-1);
totalSeconds += durationValue * multipliers[durationType];
}
const totalMinutes = Math.floor(totalSeconds / 60);
const remainderSeconds = totalSeconds % 60;
return `${totalMinutes}m ${totalSeconds}s`;
}

Related

Convert partial number to written word form in Google Sheets (e.g. 1300 to 1.3 thousand)? [duplicate]

is there a way how to custom format ridiculously large numbers (at least up to 10^100 in both ways) in google sheets:
thousands > K
millions > M
billions > B
trillions > T
etc...
negative quadrillions > Q
decillions > D
either via:
internal custom number formatting
formula (array formula ofc)
script similar to this one just extended to cover more ground
10000.1 10.0K
100 100.0
1000 1.0K
10000 10.0K
-100000 -100.0K
45646454 45.6M
5654894844216 5.7T
4655454544 4.7B
46546465455511 46.5T
-46546465455511 -46.5T
4654646545551184854556546454454400000000000000000000000000010000000 4.7U
-1000.9999 -1.0K
-100.8989 -100.9
-20.354 -20.4
1.03 1.0
22E+32 2.2D
internal custom number formatting solution:
sadly, the internal formatting in google sheets is by default able to work with only 3 types of numbers:
positive (1, 2, 5, 10, ...)
negative (-3, -9, -7, ...)
zero (0)
this can be tweaked to show custom formatting like thousands K, millions M and regular small numbers:
[>999999]0.0,,"M";[>999]0.0,"K";0
or only thousands K, millions M, billions B
[<999950]0.0,"K";[<999950000]0.0,,"M";0.0,,,"B"
or only negative thousands K, negative millions M, negative billions B
[>-999950]0.0,"K";[>-999950000]0.0,,"M";0.0,,,"B"
or only millions M, billions B, trillions T:
[<999950000]0.0,,"M";[<999950000000]0.0,,,"B";0.0,,,,"T"
or only numbers from negative million M to positive million M:
[>=999950]0.0,,"M";[<=-999950]0.0,,"M";0.0,"K"
but you always got only 3 slots you can use, meaning that you can't have trillions as the 4th type/slot. fyi, the 4th slot exists, but it's reserved for text. to learn more about internal formatting in google sheets see:
https://developers.google.com/sheets/api/guides/formats#meta_instructions
https://www.benlcollins.com/spreadsheets/google-sheets-custom-number-format/
formula (array formula) solution:
the formula approach is more versatile... first, you will need to decide on the system/standard you want to use (American, European, Greek, International, Unofficial, etc...):
en.wikipedia.org/wiki/Names_of_large_numbers
en.wikipedia.org/wiki/Metric_prefix
simple.wikipedia.org/wiki/Names_for_large_numbers
home.kpn.nl/vanadovv/BignumbyN
after that try:
=INDEX(REGEXREPLACE(IFNA(TEXT(A:A/10^(VLOOKUP(LEN(TEXT(INT(ABS(A:A)), "0"))-1,
SEQUENCE(35, 1,, 3), 1, 1)), "#.0")&VLOOKUP(ABS(A:A)*1, {{10^SEQUENCE(34, 1, 3, 3)},
{"K "; "M "; "B "; "T "; "Qa "; "Qi "; "Sx "; "Sp "; "O "; "N "; "D "; "Ud ";
"Dd "; "Td "; "Qad"; "Qid"; "Sxd"; "Spd"; "Od "; "Nd "; "V "; "Uv "; "Dv "; "Tv ";
"Qav"; "Qiv"; "Sxv"; "Spv"; "Ov "; "Nv "; "Tr "; "Ut "; "Dt "; "Tt "}}, 2, 1),
IF(ISBLANK(A:A),, TEXT(A:A, "0.0 "))), "^0\.0 $", "0 "))
works with positive numbers
works with negative numbers
works with zero
works with decimal numbers
works with numeric values
works with plain text numbers
works with scientific notations
works with blank cells
works up to googol 10^104 in both ways
extra points if you are interested in how it works...
let's start with virtual array {{},{}}. SEQUENCE(34, 1, 3, 3) will give us 34 numbers in 1 column starting from number 3 with the step of 3 numbers:
these will be used as exponents while rising 10 on the power ^
so our virtual array will be:
next, we insert it as the 2nd argument of VLOOKUP where we check ABS absolute values (converting negative values into positive) of A column multiplied by *1 just in case values of A column are not numeric. via VLOOKUP we return the second 2 column and as the 4th argument, we use approximate mode 1
numbers from -999 to 999 will intentionally error out at this point so we could later use IFNA to "fix" our errors with IF(A:A=IF(,,),, TEXT(A:A, "#.0 ")) translated as: if range A:A is truly empty ISBLANK output nothing, else format A column with provided pattern #.0 eg. if cell A5 = empty, the output will be blank cell... if -999 < A5=50 < 999 the output will be 50.0
and the last part:
TEXT(A:A/10^(VLOOKUP(LEN(TEXT(INT(ABS(A:A)), "0"))-1,
SEQUENCE(35, 1,, 3), 1, 1)), "#.0")
ABS(A:A) to convert negative numbers into positive. INT to remove decimal numbers if any. TEXT(, "0") to convert scientific notations 3E+8 into regular numbers 300000000. LEN to count digits. -1 to correct for base10 notation. VLOOKUP above-constructed number in SEQUENCE of 35 numbers in 1 column, this time starting from number 0 ,, with the step of 3 numbers. return via VLOOKUP the first 1 column (eg. the sequence) in approximate mode 1 of vlookup. insert this number as exponent when rising the 10 on power ^. and take values in A column and divide it by the above-constructed number 10 raised on the power ^ of a specific exponent. and lastly, format it with TEXT as #.0
to convert ugly 0.0 into beautiful 0 we just use REGEXREPLACE. and INDEX is used instead of the longer ARRAYFORMULA.
sidenote: to remove trailing spaces (which are there to add nice alignment lol) either remove them from the formula or use TRIM right after INDEX.
script solution:
gratitude to #TheMaster for covering this
here is a mod of it:
/**
* formats various numbers according to the provided short format
* #customfunction
* #param {A1:C100} range a 2D array
* #param {[X1:Y10]} database [optional] a real/virtual 2D array
* where the odd column holds exponent of base 10
* and the even column contains format suffixes
* #param {[5]} value [optional] fix suffix to fixed length
* by padding spaces (only if the second parameter exists)
*/
// examples:
// =CSF(A1:A)
// =CSF(2:2; X5:Y10)
// =CSF(A1:3; G10:J30)
// =CSF(C:C; X:Y; 2) to use custom alignment
// =CSF(C:C; X:Y; 0) to remove alignment
// =INDEX(TRIM(CSF(A:A))) to remove alignment
// =CSF(B10:D30; {3\ "K"; 4\ "TK"}) for non-english sheets
// =CSF(E5, {2, "deci"; 3, "kilo"}) for english sheets
// =INDEX(IF(ISERR(A:A*1); A:A; CSF(A:A))) to return non-numbers
// =INDEX(IF((ISERR(A:A*1))+(ISBLANK(A:A)), A:A, CSF(A:A*1))) enforce mode
function CSF(
range,
database = [
[3, 'K' ], //Thousand
[6, 'M' ], //Million
[9, 'B' ], //Billion
[12, 'T' ], //Trillion
[15, 'Qa' ], //Quadrillion
[18, 'Qi' ], //Quintillion
[21, 'Sx' ], //Sextillion
[24, 'Sp' ], //Septillion
[27, 'O' ], //Octillion
[30, 'N' ], //Nonillion
[33, 'D' ], //Decillion
[36, 'Ud' ], //Undecillion
[39, 'Dd' ], //Duodecillion
[42, 'Td' ], //Tredecillion
[45, 'Qad'], //Quattuordecillion
[48, 'Qid'], //Quindecillion
[51, 'Sxd'], //Sexdecillion
[54, 'Spd'], //Septendecillion
[57, 'Od' ], //Octodecillion
[60, 'Nd' ], //Novemdecillion
[63, 'V' ], //Vigintillion
[66, 'Uv' ], //Unvigintillion
[69, 'Dv' ], //Duovigintillion
[72, 'Tv' ], //Trevigintillion
[75, 'Qav'], //Quattuorvigintillion
[78, 'Qiv'], //Quinvigintillion
[81, 'Sxv'], //Sexvigintillion
[84, 'Spv'], //Septenvigintillion
[87, 'Ov' ], //Octovigintillion
[90, 'Nv' ], //Novemvigintillion
[93, 'Tr' ], //Trigintillion
[96, 'Ut' ], //Untrigintillion
[99, 'Dt' ], //Duotrigintillion
[100, 'G' ], //Googol
[102, 'Tt' ], //Tretrigintillion or One Hundred Googol
],
value = 3
) {
if (
database[database.length - 1] &&
database[database.length - 1][0] !== 0
) {
database = database.reverse();
database.push([0, '']);
}
const addSuffix = num => {
const pad3 = (str = '') => str.padEnd(value, ' ');
const decim = 1 // round to decimal places
const separ = 0 // separate number and suffix
const anum = Math.abs(num);
if (num === 0)
return '0' + ' ' + ' '.repeat(separ) + ' '.repeat(decim) + pad3();
if (anum > 0 && anum < 1)
return String(num.toFixed(decim)) + ' '.repeat(separ) + pad3();
for (const [exp, suffix] of database) {
if (anum >= Math.pow(10, exp))
return `${(num / Math.pow(10, exp)).toFixed(decim)
}${' '.repeat(separ) + pad3(suffix)}`;
}
};
return customFunctionRecurse_(
range, CSF, addSuffix, database, value, true
);
}
function customFunctionRecurse_(
array, mainFunc, subFunc, ...extraArgToMainFunc
) {
if (Array.isArray(array))
return array.map(e => mainFunc(e, ...extraArgToMainFunc));
else return subFunc(array);
}
sidenote 1: this script does not need to be authorized priorly to usage
sidenote 2: cell formatting needs to be set to Automatic or Number otherwise use enforce mode
extra:
convert numbers into plain text strings/words
convert array of numbers into plain text strings/words
convert custom formatted numbers into numeric numbers/values
convert text string datetime into duration value
convert text string formatted numbers into duration
convert your age into years-months-days
For almost all practical purposes we can use Intl compact format to achieve this functionality.
/**
* Utility function needed to recurse 2D arrays
*/
function customFunctionRecurse_(
array,
mainFunc,
subFunc,
...extraArgToMainFunc
) {
if (Array.isArray(array))
return array.map(e => mainFunc(e, ...extraArgToMainFunc));
else return subFunc(array);
}
/**
* Simple custom formating function using Intl
* #see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat
* #customfunction
* #author TheMaster https://stackoverflow.com/users/8404453
* #param {A1:D2} numArr A 2D array
* #returns {String[][]}Compact Intl formatted 2D array
*/
function format(numArr) {
const cIntl = new Intl.NumberFormat('en-GB', {
notation: 'compact',
compactDisplay: 'short',
});
return customFunctionRecurse_(numArr, format, (num) => cIntl.format(num));
}
But for extreme ends or custom formatting, We need to use a custom script:
/**
* Formats various numbers according to the provided format
* #customfunction
* #author TheMaster https://stackoverflow.com/users/8404453
* #param {A1:D2} numArr A 2D array
* #param {X1:Y2} formatArr [optional] A format 2D real/virtual array
* with base 10 power -> suffix mapping
* eg: X1:3 Y1:K represents numbers > 10^3 should have a K suffix
* #param {3} suffixPadLength [optional] Fix suffix to fixed length by padding spaces
* #returns {String[][]} Formatted 2D array
*/
function customFormat(
numArr,
formatArr = [
/**This formatArr array is provided by
* by player0 https://stackoverflow.com/users/5632629/
* #see https://stackoverflow.com/questions/69773823#comment123503634_69809210
*/
[3, 'K'], //Thousand
[6, 'M'], //Million
[9, 'B'], //Billion
[12, 'T'], //Trillion
[15, 'Qa'], //Quadrillion
[18, 'Qi'], //Quintillion
[21, 'Sx'], //Sextillion
[24, 'Sp'], //Septillion
[27, 'O'], //Octillion
[30, 'N'], //Nonillion
[33, 'D'], //Decillion
[36, 'Ud'], //Undecillion
[39, 'Dd'], //Duodecillion
[42, 'Td'], //Tredecillion
[45, 'Qad'], //Quattuordecillion
[48, 'Qid'], //Quindecillion
[51, 'Sxd'], //Sexdecillion
[54, 'Spd'], //Septendecillion
[57, 'Od'], //Octodecillion
[60, 'Nd'], //Novemdecillion
[63, 'V'], //Vigintillion
[66, 'Uv'], //Unvigintillion
[69, 'Dv'], //Duovigintillion
[72, 'Tv'], //Trevigintillion
[75, 'Qav'], //Quattuorvigintillion
[78, 'Qiv'], //Quinvigintillion
[81, 'Sxv'], //Sexvigintillion
[84, 'Spv'], //Septenvigintillion
[87, 'Ov'], //Octovigintillion
[90, 'Nv'], //Novemvigintillion
[93, 'Tr'], //Trigintillion
[96, 'Ut'], //Untrigintillion
[99, 'Dt'], //Duotrigintillion
[102, 'G'], //Googol
],
suffixPadLength = 3,
inRecursion = false
) {
if (!inRecursion) {
formatArr = formatArr.reverse();
formatArr.push([0, '']);
}
const addSuffix = num => {
const pad3 = (str = '') => str.padEnd(suffixPadLength, ' '); //pad 3 spaces if necessary
const anum = Math.abs(num);
if (num === 0) return '0' + pad3();
if (anum > 0 && anum < 1) return String(num.toFixed(2)) + pad3();
for (const [exp, suffix] of formatArr) {
if (anum >= Math.pow(10, exp))
return `${(num / Math.pow(10, exp)).toFixed(2)}${pad3(suffix)}`;
}
};
return customFunctionRecurse_(
numArr,
customFormat,
addSuffix,
formatArr,
suffixPadLength,
true
);
}
Usage:
=CUSTOMFORMAT(A1:A5,{{3,"k"};{10,"G"}})
Tells custom function to use k for numbers>10^3 and G for 10^10
Illustration:
/*<ignore>*/console.config({maximize:true,timeStamps:false,autoScroll:false});/*</ignore>*/
/**
* Utility function needed to map 2D arrays
*/
function customFunctionRecurse_(array, mainFunc, subFunc, extraArgToMainFunc) {
if (Array.isArray(array))
return array.map((e) => mainFunc(e, extraArgToMainFunc));
else return subFunc(array);
}
/**
* Simple custom formating function using Intl
* #see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat
* #customfunction
* #param {A1:D2} A 2D array
* #returns {String[][]}Compact Intl formatted 2D array
*/
function format(numArr) {
const cIntl = new Intl.NumberFormat('en-GB', {
notation: 'compact',
compactDisplay: 'short',
});
return customFunctionRecurse_(numArr, format, (num) => cIntl.format(num));
}
/**
* Formats various numbers according to the provided format
* #customfunction
* #param {A1:D2} A 2D array
* #param {X1:Y2=} [optional] A format 2D real/virtual array
* with base 10 power -> suffix mapping
* eg: X1:3 Y1:K represents numbers > 10^3 should have a K suffix
* #returns {String[][]} Formatted 2D array
*/
function customFormat(
numArr,
formatArr = [
//sample byte => kb formatting
[3, 'kb'],
[6, 'mb'],
[9, 'gb'],
[12, 'tb'],
]
) {
//console.log({ numArr, formatArr });
if (
formatArr[formatArr.length - 1] &&
formatArr[formatArr.length - 1][0] !== 0
) {
formatArr = formatArr.reverse();
formatArr.push([0, '']);
}
const addSuffix = (num) => {
const anum = Math.abs(num);
if (num === 0) return '0.00';
if (anum > 0 && anum < 1) return String(num.toFixed(2));
for (const [exp, suffix] of formatArr) {
if (anum >= Math.pow(10, exp))
return `${(num / Math.pow(10, exp)).toFixed(2)}${suffix}`;
}
};
return customFunctionRecurse_(numArr, customFormat, addSuffix, formatArr);
}
console.log(
customFormat([
[
0,
1000,
153,
12883255,
235688235123,
88555552233355888,
-86555,
0.8523588055,
Math.pow(10, 15),
],
])
);
<!-- https://meta.stackoverflow.com/a/375985/ --> <script src="https://gh-canon.github.io/stack-snippet-console/console.min.js"></script>
sometimes when we deal with nuclear physics we need to shorten the time so this is how:
=INDEX(IF(ISBLANK(A2:A),,TEXT(TRUNC(TEXT(IF(A2:A*1<1,
TEXT(A2:A*1, "0."&REPT(0, 30))*VLOOKUP(A2:A*1, {SORT({0; 1/10^SEQUENCE(9, 1, 3, 3)}),
{0; 10^SORT(SEQUENCE(9, 1, 3, 3), 1,)}}, 2, 1), TEXT(A2:A*1, REPT(0, 30))/
VLOOKUP(A2:A*1, TEXT({1; 60; 3600; 86400; 31536000; 31536000*10^SEQUENCE(8, 1, 3, 3)},
{"#", "#"})*1, 2, 1)), "0."&REPT("0", 30)), 3), "0.000")&" "&
VLOOKUP(A2:A*1, {SORT({0; 1/10^SEQUENCE(9, 1, 3, 3);
{1; 60; 3600; 86400; 31536000}; 31536000*10^SEQUENCE(8, 1, 3, 3)}), FLATTEN(SPLIT(
"s ys zs as fs ps ns μs ms s m h d y ky My Gy Ty Py Ey Zy Yy", " ",,))}, 2, 1)))
it's a simple conversion from seconds into abbreviation utilizing the International System of Units where:
in seconds
____________________________________
ys = yoctosecond = 0.000000000000000000000001
zs = zeptosecond = 0.000000000000000000001
as = attosecond = 0.000000000000000001
fs = femtosecond = 0.000000000000001
ps = pikosecond = 0.000000000001
ns = nanosecond = 0.000000001
μs = microsecond = 0.000001
ms = millisecond = 0.001
s = second = 1
m = minute = 60
h = hour = 3600
d = day = 86400
y = year = 31536000
ky = kiloyear = 31536000000
My = megayear = 31536000000000
Gy = gigayear = 31536000000000000
Ty = terayear = 31536000000000000000
Py = petayear = 31536000000000000000000
Ey = exayear = 31536000000000000000000000
Zy = zettayear = 31536000000000000000000000000
Yy = yottayear = 31536000000000000000000000000000

Dart : Show the time until the next time

How to show a countdown time duration until the next alarm
Code:
TimeOfDay _nextSalah(List<SalahModel> salahs) {
DateTime now = DateTime.now();
List<TimeOfDay> times = [];
int currentSalah;
salahs.forEach((s) => times.add(s.time));
times.add(TimeOfDay(hour: now.hour, minute: now.minute));
times.sort((a, b) => a.hour.compareTo(b.hour));
currentSalah = times.indexWhere((time) => time.hour == now.hour);
return TimeOfDay(hour: times[currentSalah].hour, minute: times[currentSalah].minute);
}
But the time difference is wrong and it doesn't animate. Also how to make sure the time difference works when it's the same day and time of the next day i.e. now is Dec 1 2:30 PM and I want to get the difference on Dec 2 6:15 AM.
It does not work because TimeOfDay represents a time during the day, independent of the date that day might fall on or the time zone. The time is represented only by hour and minute.
If you want a countdown that spans multiple days a DateTime must be used and the time difference evaluation needs some math before formatting the result string, something like:
String nextTime(DateTime nextAlarmTime) {
List<int> ctime = [0, 0, 0, 0];
DateTime now = DateTime.now();
int diff = nextAlarmTime.difference(now).inSeconds;
ctime[0] = diff ~/ (24 * 60 * 60); // days
diff -= ctime[0] * 24 * 60 * 60;
ctime[1] = diff ~/ (60 * 60); // hours
diff -= ctime[1] * 60 * 60;
ctime[2] = diff ~/ 60; // minutes
ctime[3] = diff - ctime[2] * 60; // seconds
return ctime.map((val) => val.toString().padLeft(2, '0')).join(':');
}

Elapsed time from two dates

How to display duration time between two dates to looks like :
A1 = 22.01.15
A2 = 25.08.16
A3 = "1y 7m 3d"
What code need for A3 ?
M2 = 22.01.15
M4 = 28.08.16
M5 = "1y 7m 6d"
where M5 code is
=CONCATENATE(TRUNC((M4-M2) / ( 365); 0); "y "; TRUNC(((M4-M2)-TRUNC((M4-M2) / ( 365); 0)*365) / 30;0); "m " ; TRUNC(((M4-M2)-TRUNC((M4-M2) / ( 365); 0)*365 - TRUNC(((M4-M2)-TRUNC((M4-M2) / ( 365); 0)*365) / 30;0)*30);0); "d" )

Adding time Strings in swift

I have an array of timeStrings of the following format:
x Hr(s) xx min.
I need to add these up to give a total. I'm wondering what is the best way to do this?
My thoughts were to find the index of "Hr(s)". Then if i substring between index 0 and the index of "Hr(s)", I have my hrs var and then add 6 to index of "Hr(s)" and find the index of "min" - 1, to give me the min var.
Then I need to take into account if seconds is greater than 60. So if I divide my seconds var by 60 and the answer is great than 1, I add that answer to my hrs var?
Can anyone see any flaws in this logic?
Sample implementation:
JSON response:
{"status":"OK","hrs":[{"scheduleDate":"2015-11-09","userName":"John Doe","company":"Company X","hrsWorked":"0 Hr(s) 42 min"},{"scheduleDate":"2015-11-10","userName":"Jane Doe","company":"Company Y","hrsWorked":"0 Hr(s) 47 min"},{"scheduleDate":"2015-11-10","userName":"Bob loblaw","company":"Company X","hrsWorked":"0 Hr(s) 37 min"},{"scheduleDate":"2015-11-10","userName":"Joe Soap","company":"Company Y","hrsWorked":"0 Hr(s) 50 min"},{"scheduleDate":"2015-11-10","userName":"Test","company":"Company Y","hrsWorked":"0 Hr(s) 40 min"}],"queryStatus":"OK","message":null,"count":5}
var hrsVar = 0
var minsVar = 0
loop through hrsArray{
hrsMinStr = hrsWorkedInJson
if let endHrsIndex = hrsMinStr.lowercaseString.characters.indexOf("Hr(s)") {
print("Index: \(index)")
let hrsStr = Int(hrsMinStr.substringWithRange(Range<String.Index>(start: 0, end: endHrsIndex)))
hrsVar += hrsStr
let minStr = Int(hrsMinStr.substringWithRange(Range<String.Index>(start: endHrsIndex + 1, end: hrsMinStr.length - 3)))
minsVar += minStr
}
}
if minsVar/60 > 1 {
hrsVar = hrsVar + minsVar/60
minsVar = minsVar%60
}
Update
It seems as though I cannot pass in "Hr(s)" and instead only a single character "h". Because of this, I was trying to use the advancedBy(x) method to get the right endIndex. But I'm getting the error:
Cannot invoke initializer for type 'Range<Index>' with an argument list of type '(start: Int, end: String.CharacterView.Index)'
Updated code:
if let endHrsIndex = hrsMinStr.lowercaseString.characters.indexOf("h") {
print("Index: \(endHrsIndex)")
let hrsStr = Int(hrsMinStr.substringWithRange(Range<String.Index>(start: 0, end: endHrsIndex)))
hrsVar += hrsStr
let minStr = Int(hrsMinStr.substringWithRange(Range<String.Index>(start: endHrsIndex.advancedBy(5), end: hrsMinStr.length.characters.count.advancedBy(-3))))
minsVar += minStr
}
I'm really looking for the most efficient approach as possible, so please advise if there is a better way/if you see issues with this approach
import Foundation
let str = "0 Hr(s) 42 min"
let time = str
.stringByReplacingOccurrencesOfString("Hr(s)", withString:":")
.stringByReplacingOccurrencesOfString("min", withString: "")
.stringByReplacingOccurrencesOfString(" ", withString: "")
let t = time.characters.split(Character(":"))
let h = Int(String(t[0])) // 0
let m = Int(String(t[1])) // 1
and sum
import Foundation
var time: [(hours:Int,minutes:Int,seconds:Int)] = []
for i in 0...5 {
let h = Int(arc4random_uniform(24))
let m = Int(arc4random_uniform(60))
let s = Int(arc4random_uniform(60))
time.append((h,m,s))
}
let t = time.reduce(0) { (sum, time: (hours: Int, minutes: Int, seconds: Int)) -> Int in
sum + time.seconds + time.minutes * 60 + time.hours * 60 * 60
}
let seconds = t % 60
let minutes = ((t - seconds) / 60) % 60
let hours = ((t - seconds) / 3660)
time.forEach {
print(String(format: " %6d:%02d:%02d", arguments: [$0.hours,$0.minutes, $0.seconds]))
}
print("-------------------")
print(String(format: "Sum: %6d:%02d:%02d", arguments: [hours,minutes,seconds]))
/*
12:25:04
2:43:36
14:09:35
11:59:43
10:39:19
23:32:14
-------------------
Sum: 74:29:31
*/
You should most likely try using the scanners in your case.
let string = "12 Hr(s) 37 min"
let scanner = NSScanner(string: string)
var min: Int = 0
var hour : Int = 0
scanner.scanInteger(&hour)
scanner.scanString("Hr(s) ", intoString: nil)
scanner.scanInteger(&min)
Or even easier if you create this part in Objective-C:
int min, hour;
sscanf("12 Hr(s) 37 min", "%d Hr(s) %d min", &hour, &min);

Angular Directive to replace html not working on iOS

I have this piece of code:
(function() {
"use strict";
angular
.module("Default")
.directive(
"numberToTime",
["$rootScope", "$compile", "$log",
function($rootScope, $compile, $log) {
return {
"restrict": "A",
"transclude": true,
"replace": true,
"scope": {
"time": "="
},
"link": function(scope, ele, attrs) {
/**
* Function to add one serie of string to another untill complete
* certain length
*
*/
var _lpad = function(str, padString, length) {
while (str.length < length) {
str = padString + str;
}
return str;
};
/**
* Function to turn a number into time format
*/
var _2time = function(s, hideDays, hideSeconds) {
var d = Math.floor(s / (24 * 60 * 60));
s -= d * (24 * 60 * 60);
var h = Math.floor(s / (60 * 60));
s -= h * (60 * 60);
var m = Math.floor(s / 60);
s -= m * 60;
s = Math.floor(s);
var time = "";
if (!hideDays) {
time += d > 0 ? d + " day" + (d > 1 ? "s" : "") + ", " : "";
}
time += _lpad(h.toString(), '0', 2) + ":" + _lpad(m.toString(), '0', 2) + (hideSeconds ? "" : (":" + _lpad(s.toString(), '0', 2)));
return time;
};
var _setTime = function(time) {
var _time = _2time(time, attrs.hidedays != "false", attrs.hideseconds != "false");
ele.html(_time);
};
scope.$watch("time", function() {
_setTime(scope.time);
}, true);
}
};
}
]
)
;
})();
It works ok, if I have something like:
<span number-to-time time="time"></span>
where
$scope.time = 1234;
It turns that number into readable time format. However, in iOS it does not updates the html.
I have it in a player, and if I log the html() content of ele, it says it has the correct time, but in the page I still see 00:00:00, and the time does not updates correctly. What am I doing wrong?
FIXING
Instead of using .html use .text:
ele.text(_time);
Looks like your page is not being rendered. Instead of using html, use text.
var _setTime = function(time) {
var _time = _2time(time, attrs.hidedays != "false", attrs.hideseconds != "false");
ele.text(_time);
};
You can find more information here: http://bit.ly/1E4cMxG

Resources