Dodawanie godzin w JavaScript

W naszej aplikacji możemy wpisywać tematy oraz imię i nazwisko prelegenta. Jednak tak naprawdę nic więcej się nie dzieje poza przepisaniem tych danych i dodaniem odpowiednich cudzysłowów i myślników. Dodajmy obliczanie godzin występów!

Chcemy do godziny rozpoczęcia wystąpienia np. 16:50 dodać jego czas trwania np. 15 minut, zapisane w formacie 00:15. Powinniśmy otrzymać godzinę zakończenia danego wystąpienia tj. 17:15. Dzięki takiemu formatowi, będziemy mogli wpisywać wystąpienia trwające dłużej niż godzinę np. półtorej godziny będzie zapisane 01:30.

W JavaScript niestety nie ma gotowej funkcji pozwalającej na sprasowanie godziny w takim formacie, ani ich dodawanie. Niemożliwe jest też dodanie własnego formatu (jak to można zrobić np. w Javie za pomocą DateTimeFormatter).

Własna funkcja dodająca godziny

Napiszmy więc własną funkcję. Chcemy przyjąć dwa parametry addTime(start, time):

  • start np. "16:50",
  • czas do dodania np. "00:15".

Wynikiem wywołania funkcji addTime("16:50", "00:15") powinien być tekst: "17:05".

Jak zaimplementować tę funkcję? Stwórzmy nowy obiekt new Date() i przypiszmy go do jakiejś zmiennej np. o nazwie now. Ustawmy godziny i minuty z pierwszego parametru za pomocą setHourssetMinutes. Następnie pobierzmy liczbę godzin i minut z drugiego parametru i dodajmy je do naszego obiektu (osobno godziny, osobno minuty).

Przykładowo jeśli liczbą minut z pierwszego parametru będzie 50, a będziemy chcieli dodać 25, to sumą będzie 75. Co się stanie jak ustawimy to jako minuty?

Tu JavaScript zachowa się ładnie i dostaniemy dokładnie to co chcieliśmy (licznik w godzinie się „przekręci”, wskoczy następna godzina i dostaniemy prawidłową liczbę minut; jest to niejakie dzielenie modulo 60).

Jak pobrać godziny i minuty z formatu HH:mm?

Jak już wspomniałem, nie ma w JavaScript możliwości dodania własnych formaterów. Po prostu pobierzmy odpowiednie liczby z ciągu tekstowego np. za pomocą metody split.

Metoda split(separator) działa w ten sposób, że zwraca tablicę z fragmentami tekstu podzielonymi za pomocą separatora. U nas separatorem będzie dwukropek „:”.

O to nam chodziło.

Kod funkcji będzie wyglądał tak:

Niby działa:

Ale w przypadku innych danych brakuje zer wiodących:

Zera wiodące

Zauważmy, że jeśli pobierzemy godzinę, minuty lub sekundy, które są poniżej 10, to otrzymamy liczbę bez zer wiodących:

Wynik:

Nie znalazłem eleganckiego rozwiązania. Trzeba po prostu zrobić if-a, który będzie to sprawdzał i doklejał „0” w odpowiednim miejscu:

Krócej można to zapisać:

Wynikiem będzie tekst:

Nasza poprawna funkcja będzie teraz wyglądać tak:

Jak widzimy, teraz wszystko działa poprawnie:

Wykorzystanie funkcji w AgendaEditor

Mamy gotową funkcję obliczającą godziny. Dodajmy ją do projektu.

Zmiany w HTML

Naszym widokiem z agendą obecnie jest plik home.html. Przede wszystkim musimy dodać tam pola gdzie będziemy mogli wpisać dane. Dodanie kolumny z miejscem na czas wystąpienia („time”):

Jak widzimy, system gridowy możemy stosować również do kolumn tabel, tak jak do całej strony.

Jako nowy wiersz wstawiamy dodatkowe pole analogiczne do innych:

Zostało nam do dodania pole, w które będziemy wpisywać godzinę startu całego wydarzenia. Dodajmy je nad tabelą:

Skorzystaliśmy z klasy form-group, w elemencie nią oznaczoną możemy umieścić napis label. Ustawiamy mu szerokość taką samą jak dla kolumny wyżej „Time” tzn. col-sm-2. Dodajmy również offset, który umieści pole nad kolumną tabeli „Time”. Po lewej stronie są kolumny „Title” (5), „Name” (2), „Surname” (2), co razem daje 5+2+2=9. Dlatego offset jest równy: col-sm-offset-9. Do tego nasze pole (2) i jeszcze puste miejsce, pod którym jest przycisk do usuwania (1), razem daje 12 bootstrapowych kolumn.

Zmiany w JavaScript

Przejdźmy teraz do naszego Angularowego kontrolera home.js.

Dodajmy naszą funkcję. W kodzie poniżej widzimy, że musimy ją wstawić dokładnie w kontrolerze. Nie będziemy jej przypisywać do $scope, bo nie ma takiej potrzeby (będzie wykorzystywana tylko lokalnie w kontrolerze):

W naszej liście $scope.list na początku umieszczamy jeden element za pomocą push. Pamiętajmy aby dodać tam nowe pole time: "", tak jak w kodzie wyżej.

Zajmijmy się teraz funkcją $scope.myResult, w której powinny wystąpić wywołania funkcji addTime, aby obliczyć godziny wystąpień.

Poprzednia wersja wyglądała tak:

Dodajmy sobie zmienną lastTime przechowującą godzinę zakończenia poprzedniego wystąpienia. Będzie to automatycznie początek kolejnego wystąpienia. Na początku oczywiście musimy ustawić ją jako czas startowy całego wydarzenia:

W pętli będziemy obliczać koniec wystąpienia za pomocą naszej funkcji addTime:

Oczywiście obliczone godziny musimy dopisywać do wykonu końcowego.

Oprócz tego dodajmy kilka warunków:

  • Nie wykonuj pętli (czyli nie rób niczego z naszą listą), jeśli nie została wpisana godzina wystąpienia:
  • Nie przetwarzaj danego wiersza jeśli nie został wpisany tytuł lub jeśli nie został wpisany czas wystąpienia (czasem zdarza się pusty string a czasem undefined).

Cały kod funkcji myResult będzie teraz wyglądał tak:

Podgląd działającej aplikacji

W zakładce „Code” oczywiście można podejrzeć kod całej aplikacji. Klikając tutaj, otworzymy ją w nowej karcie.

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *