MATLAB - Datetime - część 2

W poprzednim poście poruszyłem ogólnie temat datetime w MATLABie zwracając Waszą uwagę na wygodę posługiwania się tym typem danych. Pokazałem Wam jak importować poprawnie dane opisujące czas z zewnętrznych plików. Dzisiaj czas na kilka konkretnych przykładów.
Generowanie daty i konwersja między różnymi typami danych

Nawiązując jeszcze do pracy z danymi, które są importowane do MATLABa z zewnętrznego programu, często zdarza się tak, że każdy element opisujący datę, to jest dni, miesiące, lata, godziny, itd., jest zapisany jako osobna zmienna w postaci liczby (typ numeryczny). Może być też tak, że data jest zapisana jako zwykły tekst. Miałem do czynienia z taką sytuacją, wiele razy, kiedy system pomiarowy zapisywał datę właśnie w taki sposób. Jak sobie z tym poradzić?

Załóżmy, że data jest opisana przez wektory typu kolumnowego. Rok to jeden wektor, miesiąc to inny wektor i tak dalej. Poniżej jest program, który scala te pojedyncze wektory w jedną zmienną typu datetime:

clear all; close all; clc

% Mamy osobne wektory kolumnowe opisujące rok, miesiąc, itd. 
% Odpowiadające sobie elementy wektorów tworzą pojedynczą 
% datę/chwilę czasu.

rok = [2021; 2021; 2021; 2021];
miesiac = [11; 11; 11; 11];
dzien = [1; 2; 3; 4];
godzina = [9; 17; 16; 23];
minuty = [44; 2; 12; 0];
sekundy = [1; 58; 57; 43];

% Użycie funkcji datetime:
data1 = datetime(rok, miesiac, dzien, godzina, minuty, sekundy)

% Jeżeli mamy jedną macierz zawierającą kilka kolumn, 
% postępujemy podobnie:
data_macierz = [rok, miesiac, dzien, godzina, minuty, sekundy];
data2 = datetime(data_macierz)

% Oba przekształcenia dadzą ten sam wynik.

Należy pamiętać, że typ datetime, a tym samym funkcja o tej samej nazwie wymaga podania co najmniej trzech elementów daty: roku, miesiąca i dnia lub godziny, minuty i sekundy. Oczywiście można podać wszystkie te sześć argumentów naraz. Nie da się natomiast utworzyć zmiennej datetime podając na przykład jedynie rok lub miesiąc i dzień.

Dysponując ciągiem dat w typie MATLABowskim datetime, możemy łatwo wykonywać podstawowe operacje, choćby takie o jakich była mowa w poprzednim poście, więc tutaj nie będę już o nich wspominał.

Natomiast jeżeli chcemy zmienić format daty z yyyy-MM-dd HH:mm:ss na inny, na przykład dd-MM-yyyy to wystarczy:

dd HH:mm:ss na inny, na przykład dd-MM-yyyy to wystarczy:

% Jeżeli chcemy zmienić format daty z yyyy-MM-dd na dd-MM-yyyy, 
% wystarczy:
data3 = datetime(data2,'Format','dd-MM-yyyy')
% jeśli interesuje nas opis słowny:
data4 = datetime(data2,'Format','eeee, MMMM d, y')

Pominięcie godziny w formacie nie oznacza, że informacja ta zostaje utracona w nowej zmiennej. Możemy powrócić do pierwotnego zapisu formatu:

data4 = datetime(data4,'Format','yyyy-MM-dd HH:mm:ss')

Oznacza to, że zmienna datetime, zawsze przechowuje pełną (źródłową) informację o dacie/godzinie. Argument Format określa tylko jak te informacje będą wyświetlane w MATLABie.

Dostęp do poszczególnych elementów danej daty można uzyskać na kilka sposobów. Dokumentacja MATLABa sugeruje użycie funkcji year, month i innych. Ja jednak wolę zastosować indeksowanie z kropką w połączeniu z tradycyjnym wskazaniem wiersza, o który chodzi. Najlepiej wyjaśni to przykład:

% Aby ten program zadziałał, wcześniej musi być uruchomiony program
% poprzedni z posta. 

% cała kolumna określająca dzień/dni:
dni = data1.Day

% dzień z konkretnego wiersza:
wybrany_dzienA = data1.Day(2)

% ten sam efekt uzyskamy poprzez:
wybrany_dzienB = day(data1(2))

Jeżeli chcemy wykonać operację polegającą na konwersji zmiennej typu datetime na dane numeryczne, to można to zrobić na kilka sposobów.

Jeżeli chcemy zbiorczo odczytać datę lub czas i każdy element zapisać do osobnej zmiennej to można użyć funkcji ymd lub hms:

% Jeżeli chcemy zbiorczo odczytać datę lub czas i każdy element
% zapisać do osobnej zmiennej to można użyć funkcji ymd lub hms:
[rok2, miesiac2, dzien2] = ymd(data1)
[godzina2, minuty2, sekundy2] = hms(data1)

Jeżeli chcemy odczytać tylko jeden element daty/czasu, to można użyć predefiniowanych funkcji i również zapisać dane do osobnych zmiennych:

% Jeżeli chcemy odczytać tylko jeden element daty/czasu, to można użyć
% predefiniowanych funkcji i również zapisać dane do osobnych zmiennych:

rok3 = year(data1)
miesiac3 = month(data1)
dzien3 = day(data1)
godzina3 = hour(data1)
minuty3 = minute(data1)
sekundy3 = second(data1)

Jeżeli chcemy natomiast przekonwertować zmienną zawierającą daty/czas w formacie datetime na jedną macierz numeryczną należy użyć funkcji datevec:

% Jeżeli chcemy natomiast przekonwertować macież zawierającą daty/czas 
% w formacie datetime na jedną macierz numeryczną należy użyć 
% funkcji datevec:
macierz_daty = datevec(data1)

W ten sposób otrzymaliśmy jedną zmienną – macierz o sześciu kolumnach, które odpowiadają kolejnym elementom daty/czasu. Załóżmy teraz, że z tej macierzy chcemy wyekstrahować konkretne kolumny i zapisać je do zmiennych/wektorów, każdy o innej nazwie. W ten sposób otrzymamy wektory analogiczne, jak te wygenerowane w programie pierwszym. Proces jest więc w pełni odwracalny, choć użycie funkcji eval wymaga nieco gimnastyki.

% Jeżeli z jakiegoś powodu z takiej "dużej" macierzy chcielibyśmy wyekstrahować
% poszczególne elementy daty (jak w przykładzie powyżej) to trzeba się trochę
% nagimnastykować: 
nazwy = ["rok4"; "miesiac4"; "dzien4"; "godzina4"; "minuty4"; "sekundy4"]

% i użyć funkcji eval, do wykonania komendy z nawiasu kwadratowego:
for k = 1:size(nazwy,1)
    eval([char(nazwy(k)) '= macierz_daty(:,' num2str(k) ')'])
end

Oczywiście to samo można uzyskać wprost za pomocą wspomnianych powyżej funkcji ymd i hms, ale tylko w przypadku gdy dysponujemy oryginalną zmienną typu datetime. Jeżeli mamy macierz numeryczną, to wyodrębnienie poszczególnych kolumn do zmiennych o różnych nazwach wykonujemy w pętli z użyciem funkcji eval.

Obliczanie przedziału czasu

Druga grupa funkcji dotycząca typu datetime dotyczy obliczania przedziału czasu. Jak pokazałem to w poprzednim poście, można to zrobić posługując się operatorem arytmetycznym „minus” lub funkcją diff:

t1 = datetime(2021,06:09,1)

% Domyślnie różnica jest wyrażana w godzinach:
roznica1 = diff(t1)

% ale możmy ja przeliczyć na lata, miesiące, dni, minuty, sekundy:
years(roznica1)
days(roznica1)
minutes(roznica1)
seconds(roznica1)

Zwróćcie uwagę: do obliczania przedziału czasu używamy funkcji z końcówką „s”: years days, w odróżnieniu od year day, używanych wcześniej do konwersji daty na typ numeryczny.

Aby policzyć ile czasu upłynęło od konkretnych dat do dnia dzisiejszego należy natomiast:

t2 = datetime('now')
roznica2 = t2 - t1
days(roznica2)

Temat uważam za wyczerpany, a więcej informacji znajdziecie w dokumentacji. Powodzenia!

(Visited 286 times, 1 visits today)

Dodaj komentarz

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