Przeliczanie sekund do dowolnego formatu
| Robert | komentarze | JavaScriptPotrzeba matką wynalazków mawiają, a tak się złożyło, że potrzebowałem funkcji która przeliczy mi czas podany w sekundach na dowolny format, na przykład H:M:S. Na StackOverflow nic ciekawego co by mnie satysfakcjonowało, więc postanowiłem się za to zabrać samodzielnie. Wpis krótki lecz treściwy.
Jednym z głównym z założeń jest spełnieniem zasady Open/Close którą, wydaje się, udało mi się spełnić. Wejściem funkcji jest oczywiście czas podany w sekundach (choć mogą to być dowolne jednostki, funkcja wydaje się być uniwersalna i elastyczna) oraz drugi parametr jakim są jednostki, a dokładniej ich wielkość względem poprzedniej. Na przykład tablica [60,60,24,7] która reprezentuje minuty, godziny, dobę(dzień) oraz tydzień.
function(time, units = [60,60,24,7]) {}
W tym miejscu zasada OC zostaje spełniona. Następnie wprowadzamy pomocniczą zmienną r która będzie przechowywała nam tablicę z obliczeniami oraz d która będzie przechowywała resztę z dzielenia. Jednostki (units) traktujemy pętlą for in.
let r = [], d;
for (let i in units) {}
Kolejnym krokiem są obliczenia czyli danie główne funkcji. Obliczamy resztę z jednostki, tak, że jeśli na wejściu będziemy mieli 72 sekundy to w pierwszym przebiegu pętli wiadomym jest, że to minuta i 12 sekund. Różnicę umieszczamy w zmiennej r, następnie czas dzielimy przez jednostkę zaokrąglając w dół.
d = time % units[i];
r.push(d);
time = Math.floor(time / units[i]);
Pojawią się przypadki kiedy na przykład funkcja zostanie potraktowana przykładem 180 sekund, wówczas to są 3 minuty, lecz funkcja zwróci 0. Nie chcemy też, aby pętla liczyła do samego końca tablicy jednostek, kiedy nie ma w zasadzie już co liczyć (doby, kiedy czas zamknął się w mniej niż 24 godzin). Wstawimy sobie następującą instrukcję warunkową if tuż po obliczeniu różnicy d:
if (d <= 0 && time == 0 && r.length > 1) break;
Dobrze, pora na zwrot akcji (plot twist hehe). Zwracamy wynik:
return r.reverse().join(':');
Co tu się stało? Odwracamy tablicę r ponieważ pętla zaczyna od sekund, następnie łączymy ją dwukropkiem. Możemy również rozbudować funkcję o kolejny parametr delimiter. Gotowa funkcja prezentuje się następująco:
function(time, units = [60,60,24,7], delimiter = ':') {
let r = [], d;
for (let i in units) {
d = time % units[i];
if (d <= 0 && time == 0 && r.length > 1) break;
r.push(d);
time = Math.floor(time / units[i]);
}
return r.reverse().join(delimiter);
};
TL;DR: Funkcja po podaniu czasu w sekundach (132) zwróci nam domyślnie wynik w formacie W:H:M:S (2:12). Może pojawić się sytuacja, kiedy w wyniku ilość sekund będzie wyłącznie jednością, wówczas dla estetyki dopisałem funkcję pomocniczą:
function(cv,j) {
return j > 0 && cv.toString().length == 1 ? '0'+cv : cv;
};
Aby skorzystać z funkcjonalności wynik z funkcji głównej należy potraktować metodą split(), map() stosując powyższą funkcję, a następnie join(). Dla przykładu całość:
function convert (time, units = [60,60,24,7], delimiter = ':') {
let r = [], d;
for (let i in units) {
d = time % units[i];
if (d <= 0 && time == 0 && r.length > 1) break;
r.push(d);
time = Math.floor(time / units[i]);
}
return r.reverse().join(delimiter);
};
function beforeZero (cv,j) {
return j > 0 && cv.toString().length == 1 ? '0'+cv : cv;
};
let = convert(182).split(':').map(beforeZero).join(':');
Proste i przyjemne.