Chciałbym napisać skrypt lub funkcję, która powie mi, ile dni od teraz do określonej daty w przyszłości. To, co próbuję wypracować, to jak przetworzyć podaną datę i porównać ją z bieżącą datą ... Wyobrażam sobie coś takiego
read -p "enter the date in the format YYYY-MM-DD "
A potem zakładam, że mam ciąg, który nie ma znaczenia dla powłoki i muszę dokonać pewnych ocen, takich jak ... ?? (To tylko przykład; myślę, bc
że będzie potrzebny)
i=$(($(date +%Y)-${REPLY%%-*}))
j=$(($(date +%m)-${REPLY:5:2}))
k=$(($(date +%d)-${REPLY##*-}))
A potem nie wiem, co zrobić z tymi liczbami ... ??
if $i > 1 then assign l=$((i*365)) and else what?? # what about leap years?
Using $j somehow assign m # confused before I've started
Using $k somehow assign n # just as bad
echo $((l+m+n))
Z pewnością utrudniam to sobie; prawdopodobnie istnieje narzędzie do przetwarzania tekstu, które rozumie daty i może je porównywać.
W jaki sposób mogę to zrobić?
Odpowiedzi:
Czas epoki
Zasadniczo obliczenia czasowe są najłatwiejsze, jeśli najpierw przekonwertujemy czas na czas (uniksowy) epoki (sekundy od 1-1-1970). W Pythonie mamy narzędzia do konwersji czasu na epokę i powrotu do dowolnego preferowanego formatu daty.
Możemy po prostu ustawić format, na przykład:
... i zdefiniuj dzisiaj:
a następnie napisz funkcję wykonującą zadanie:
Następnie dane wyjściowe:
... co jest, jak wspomniano, liczbą sekund od 1-1-1970
Obliczanie dni między dwiema datami
Jeśli zrobimy to zarówno dzisiaj, jak i w przyszłości, oblicz różnicę:
Dane wyjściowe zostaną obliczone według daty , ponieważ używamy formatu
%Y-%m-%d
. Zaokrąglanie sekund może być przyczyną nieprawidłowej różnicy dat, jeśli na przykład jesteśmy blisko 24 godzin.Wersja terminalowa
... i opcja Zenity
I dla zabawy ...
Mała aplikacja. Dodaj go do skrótu, jeśli często go używasz.
Scenariusz:
orangedays.py
Uruchom:
Podsumowując
Użyj dla małego skryptu aplikacji nad następującym
.desktop
plikiem:orangedays.desktop
w~/.local/share/applications
W linii
ustaw rzeczywistą ścieżkę do skryptu ...
źródło
GNU
date
narzędzie jest dość dobry na tego typu rzeczy. Jest w stanie przeanalizować wiele różnych formatów dat, a następnie wyprowadzać je w innym formacie. Tutaj używamy%s
do wyświetlania liczby sekund od epoki. Odejmowanie$now
od$future
i dzielenie przez 86400 sekund / dzień to prosta kwestia arytmetyczna :źródło
-u
parametr dodate
.Możesz spróbować coś zrobić
awk
, korzystając zmktime
funkcjiAwk oczekuje odczytania daty ze standardowego wejścia w formacie „RRRR MM DD GG MM SS”, a następnie wydrukuje różnicę między podanym czasem a bieżącym czasem w dniach.
mktime
po prostu konwertuje czas (w określonym formacie) na liczbę sekund z czasu odniesienia (1970-01-01 00:00:00 UTC); systime simple określa aktualny czas w tym samym formacie. Odejmij jeden od drugiego, a otrzymasz odległość od siebie w kilka sekund. Podziel przez 86400 (24 * 60 * 60), aby przeliczyć na dni.źródło
Oto wersja Ruby
Przykładowy przebieg:
Przykład uruchomienia skryptu
ruby ./day-difference.rb
podano poniżej (zakładając, że został zapisany jakoday-difference.rb
)Z przyszłą datą
Z upływem daty
Kiedy minęła dzisiejsza data
Oto fajna strona internetowa, na której można sprawdzić różnice dat http://www.timeanddate.com/date/duration.html
źródło
Istnieje
dateutils
pakiet, który jest bardzo wygodny do obsługi dat. Przeczytaj więcej na ten temat tutaj github: dateutilsZainstaluj przez
sudo apt install dateutils
W przypadku twojego problemu po prostu
dateutils.ddiff <start date> <end date> -f "%d days"
gdzie dane wyjściowe można wybrać jako sekundy, minuty, godziny, dni, tygodnie, miesiące lub lata. Można go wygodnie używać w skryptach, w których dane wyjściowe można wykorzystać do innych zadań.
Na przykład,
źródło
Możesz użyć biblioteki awk Velor :
Lub:
źródło
Krótkim rozwiązaniem, jeśli obie daty należą do tego samego roku, jest:
za pomocą formatu „% j”, który zwraca pozycję daty w dniach w roku, tj. 135 dla bieżącej daty. Pozwala to uniknąć problemów z zaokrąglaniem i obsługuje daty w przeszłości, dając negatywne wyniki.
Jednak przekroczenie granic roku nie powiedzie się. Możesz dodać (lub odjąć) 365 ręcznie dla każdego roku lub 366 dla każdego roku przestępnego, jeśli upłynie ostatni luty, ale będzie to prawie tak szczegółowe, jak inne rozwiązania.
Oto czyste rozwiązanie bash:
Shellcheck sugeruje wiele podwójnych cytatów, ale w dniach przekraczających rok 9999 należy rozważyć inne podejście. W przeszłości nie powiedzie się po cichu dla dat sprzed 1970.01.01. Odkażanie danych wejściowych użytkownika pozostaje ćwiczeniem dla użytkownika.
Dwie funkcje można przekształcić w jedną, ale może to utrudnić zrozumienie.
Pamiętaj, że skrypt wymaga wyczerpujących testów, aby poprawnie obsługiwać lata przestępne w przeszłości. Nie założę się, że to prawda.
źródło