Jak można porównać dwie daty w skorupce?
Oto przykład, w jaki sposób chciałbym tego użyć, chociaż nie działa tak, jak jest:
todate=2013-07-18
cond=2013-07-15
if [ $todate -ge $cond ];
then
break
fi
Jak mogę osiągnąć pożądany efekt?
shell-script
shell
date
Abdul
źródło
źródło
Odpowiedzi:
Nadal brakuje właściwej odpowiedzi:
Zauważ, że wymaga to daty GNU. Równoważna
date
składnia BSDdate
(domyślnie taka jak w OSX) todate -j -f "%F" 2014-08-19 +"%s"
źródło
timeout=$(`date +%Y%m%d%H%M%S` + 500)
) jest oczywiście błędny.date -d 2013-07-18 +%s%N
Brakuje formatu daty dla porównania:
Brakuje również zapętlonych struktur, jak planujesz uzyskać więcej dat?
źródło
date
dostarczonym z macOS.date -d
jest niestandardowy i nie działa na typowym systemie UNIX. Na BSD próbuje nawet ustawić wartość kenelDST
.Można użyć standardowego porównania ciągów, aby porównać chronologiczne uporządkowanie [ciągów w formacie roku, miesiąca i dnia].
Na szczęście, gdy [ciągi znaków, które używają formatu RRRR-MM-DD] są sortowane * w kolejności alfabetycznej, są one również sortowane * w kolejności chronologicznej.
(* - posortowane lub porównane)
W tym przypadku nic szczególnego nie jest potrzebne. tak!
źródło
if [ $(sed -e s/-//g <<< $todate) -ge $(sed -e s/-//g <<< $cond) ];
… Ten format daty został zaprojektowany do sortowania przy użyciu standardowego sortowania alfanumerycznego lub-
do usuwania i sortowania numerycznego.To nie jest problem pętli struktur, ale typów danych.
Te daty (
todate
icond
) są łańcuchami, a nie liczbami, więc nie można użyć operatora „-ge”test
. (Pamiętaj, że notacja w nawiasach kwadratowych jest równoważna poleceniutest
.)Możesz użyć innego zapisu dla swoich dat, aby były to liczby całkowite. Na przykład:
wygeneruje liczbę całkowitą taką jak 20130715 na 15 lipca 2013 r. Następnie możesz porównać swoje daty z „-ge” i równoważnymi operatorami.
Aktualizacja: jeśli podane są daty (np. Czytasz je z pliku w formacie 2013-07-13), możesz łatwo przetwarzać je wstępnie za pomocą tr.
źródło
Operator
-ge
działa tylko z liczbami całkowitymi, które nie są Twoimi datami.Jeśli twój skrypt to skrypt bash, ksh lub zsh, możesz
<
zamiast tego użyć operatora. Ten operator nie jest dostępny w desce rozdzielczej ani w innych powłokach, które nie wykraczają daleko poza standard POSIX.W dowolnej powłoce możesz konwertować ciągi na liczby, przestrzegając kolejności dat, po prostu usuwając myślniki.
Alternatywnie możesz przejść tradycyjnie i skorzystać z
expr
narzędzia.Ponieważ wywoływanie podprocesów w pętli może być powolne, możesz preferować wykonanie transformacji za pomocą konstrukcji przetwarzających ciąg powłoki.
Oczywiście, jeśli możesz pobrać daty bez myślników, będziesz mógł je porównać
-ge
.źródło
Przekształcam ciągi znaków na uniksowe znaczniki czasu (sekundy od 1.1.1970 0: 0: 0). Można to łatwo porównać
źródło
date
przypadku systemu MacOS.Istnieje również ta metoda z artykułu zatytułowanego: Proste obliczanie daty i godziny w BASH z unix.com.
Te funkcje są fragmentem skryptu w tym wątku!
Stosowanie
źródło
date
przypadku systemu MacOS.date
nagdate
.bash specyficzna odpowiedź
Ponieważ lubię redukować widelce, a bash pozwala na wiele lew, oto mój cel:
Więc teraz:
Spowoduje to ponowne wypełnienie obu zmiennych
$todate
i$cond
, używając tylko jednego rozwidlenia, ouptut,date -f -
który zajmie stdio do odczytu jednej daty po linii.Wreszcie możesz przerwać pętlę
Lub jako funkcja :
Korzystanie z wbudowanego basha ,
printf
które może renderować datę i czas w sekundach z epoki (patrzman bash
;-)Ten skrypt używa tylko jednego widelca.
Alternatywnie z ograniczonymi widłami i funkcją czytnika daty
Spowoduje to utworzenie dedykowanego podprocesu (tylko jeden rozwidlenie):
Ponieważ wejście i wyjście są otwarte, wpis fifo może zostać usunięty.
Funkcja:
Uwaga Aby zapobiec niepotrzebnym rozwidleniom
todate=$(myDate 2013-07-18)
, zmienna ma być ustawiana przez samą funkcję. Aby umożliwić dowolną składnię (z cudzysłowami do datestring lub bez), nazwa zmiennej musi być ostatnim argumentem.Następnie porównanie dat:
może renderować:
jeśli poza pętlą.
Lub użyj funkcji bash-shell-connector:
lub
(Które nie są dokładnie takie same:
.sh
zawierają pełny skrypt testowy, jeśli nie są pozyskiwane)źródło
date -f -
może zmniejszyć wymagania dotyczące zasobów.daty są łańcuchami, a nie liczbami całkowitymi; nie można ich porównywać ze standardowymi operatorami arytmetycznymi.
można zastosować jedno podejście, jeśli gwarantuje się, że separatorem jest
-
:Działa to już w przeszłości
bash 2.05b.0(1)-release
.źródło
Możesz także użyć wbudowanej funkcji mysql do porównania dat. Daje wynik w „dniach”.
Po prostu wstaw wartości
$DBUSER
i$DBPASSWORD
zmienne zgodnie z twoimi.źródło
FWIW: na Macu wydaje się, że wprowadzenie do daty tylko daty „2017-05-05” spowoduje dodanie bieżącej godziny do tej daty, a otrzymasz inną wartość za każdym razem, gdy zmienisz ją na czas z epoki. aby uzyskać bardziej spójny czas dla ustalonych dat, uwzględnij wartości pozorne dla godzin, minut i sekund:
Może to być osobliwość ograniczona do wersji daty dostarczonej z macOS .... testowanej na macOS 10.12.6.
źródło
Echoing @Gilles odpowiedź („Operator -ge działa tylko z liczbami całkowitymi”), oto przykład.
datetime
konwersje liczb całkowitych naepoch
, według odpowiedzi @ mike-q na https://stackoverflow.com/questions/10990949/convert-date-time-string-to-epoch-in-bash :"$curr_date"
jest większa niż (nowsza niż)"$old_date"
, ale to wyrażenie niepoprawnie ocenia jakoFalse
:... pokazane wyraźnie tutaj:
Porównanie liczb całkowitych:
źródło
Powodem, dla którego to porównanie nie działa dobrze z dzielonym ciągiem daty jest to, że powłoka przyjmuje liczbę z wiodącym 0, to ósemka, w tym przypadku miesiąc „07”. Zaproponowano różne rozwiązania, ale najszybszym i najłatwiejszym jest usunięcie łączników. Bash ma funkcję podstawiania ciągów, która sprawia, że jest to szybkie i łatwe, a następnie porównanie można wykonać jako wyrażenie arytmetyczne:
źródło