DST güvenli Linux'ta bash'de dünün tarihini öğrenin


158

Linux üzerinde çalışan ve bu çağrıyı dünün YYYY-MM-DDbiçimini almak için kullanan bir kabuk komut dosyası var :

date -d "1 day ago" '+%Y-%m-%d'

Çoğu zaman çalışır, ancak senaryo dün sabah koştuğunda bunun yerine 2013-03-11 0:35 CDTgeri döndü ."2013-03-09""2013-03-10"

Muhtemelen yaz saati uygulaması (dün başladı) suçlamaktır. Yol tahmin ediyorum "1 day ago"daha önce 24 saat, 24 saat çıkarılır uygulanmaktadır 2013-03-11 0:35 CDToldu 2013-03-09 23:35 CSTsonucuna yol açan, "2013-03-09".

Peki, dünün tarihini Linux'ta bash'de almanın iyi bir DST güvenli yolu nedir?


Bunu her zaman aynı anda mı çalıştırıyorsunuz, tekrar tekrar mı çalıştırıyorsunuz?
Mart'ta

@tink her gün 00:35
Ike Walker

Yanıtlar:


267

Ne sıklıkta ve ne zaman çalıştırdığınıza bakılmaksızın, bunun çalışması gerektiğini düşünüyorum ...

date -d "yesterday 13:00" '+%Y-%m-%d'

1
Bunu daha sonra kullanmak üzere bir değişkene nasıl atayabilirsiniz?
boş

6
@null - başka bir kabuk komutunun çıktısını atadığınız gibi. değişken = $ (tarih -d "dün 13:00" '+% Y-% m-% d') ...
tink

GNU tarihi için:date -d yesterday 13:00 -I
17'de gogstad

Bu, doğru anlarsam, yaz ve kış saati arasında geçişin her zaman gece boyunca yapılmasına dayanır?
Nicolas Raoul

2
@NicolasRaoul: Garanti edilmez; ancak bunu sabahın erken saatlerine programlamak yaygın olarak takip edilen bir sözleşmedir. Öte yandan, anahtarın yerel öğeye yakın olacağı hiçbir yer IIRC yoktur. Dolayısıyla, "1300J asla DST sınırında değildir" makul bir varsayımdır .
Piskvor

56

Mac OSX altındaki tarih biraz farklıdır.

Dün için

date -v-1d +%F

Geçen hafta için

date -v-1w +%F

8
OSX içinde GNU stilini kullanmakla ilgileniyorsanız, gdatehomebrew coreutilspaketinde bulunan kullanabilirsiniz.
user456584

11
Yani datefarklı.
augurar

12

Bu da işe yaramalı, ama belki de çok fazla:

date -d @$(( $(date +"%s") - 86400)) +"%Y-%m-%d"

Sözdizimini datedesteklemeyen Mac OS X ile uğraşmanız gerekiyorsa, bunun gibi şeyler gereklidir yesterday...
Mikko Rantalainen

7

Komut dosyasının günün ilk saatlerinde çalıştığından eminseniz,

  date -d "12 hours ago" '+%Y-%m-%d'

BTW, komut dosyası her gün 00:35'te (crontab? Yoluyla) çalışıyorsa, kendinize bir DST değişikliği o saatte düşerse ne olacağını sormalısınız; komut dosyası çalıştırılamadı veya bazı durumlarda iki kez çalıştırılamadı. Modern uygulamalar cronşunlardır oldukça zeki olsa da, bu konuda.


5

kullanabilirsiniz

date -d "30 days ago" +"%d/%m/%Y"

30 gün öncesindeki tarihi almak için, benzer şekilde 30'u x gün sayısı ile değiştirebilirsiniz


%Y%m%dSoruya uyacak şekilde biçiminizi değiştirmelisiniz . Düzgün çalıştığı için zaten iptal ettim.
isapir

4

Burada Solaris ve AIX ile de çalışacak bir çözüm.

Saat dilimini değiştirmek, saati birkaç saat değiştirmek için mümkündür. Yaz saati uygulaması nedeniyle 24 saat önce bugün veya dünden önceki gün olabilir.

Dünün 20 veya 30 saat önce olduğundan eminsiniz. Hangisi? En sonuncusu bugün değil.

echo -e "$(TZ=GMT+30 date +%Y-%m-%d)\n$(TZ=GMT+20 date +%Y-%m-%d)" | grep -v $(date +%Y-%m-%d) | tail -1

Echo komutunda kullanılan -e parametresi bash ile gereklidir, ancak ksh ile çalışmaz. Ksh içinde -e bayrağı olmadan aynı komutu kullanabilirsiniz.

Komut dosyanız farklı ortamlarda kullanıldığında, komut dosyasını #! / Bin / ksh veya #! / Bin / bash ile başlatabilirsiniz. \ N yerine bir satırsonu yazabilirsiniz:

echo "$(TZ=GMT+30 date +%Y-%m-%d)
$(TZ=GMT+20 date +%Y-%m-%d)" | grep -v $(date +%Y-%m-%d) | tail -1

0

Sadece kullanın dateve güvenilir saniye:

Haklı olarak işaret ettiğiniz gibi, İngilizce zaman aritmetiğine güveniyorsanız, temeldeki hesaplama ile ilgili birçok ayrıntı gizlenir. Örneğin -d yesterday, ve -d 1 day agofarklı davranışlar olacaktır.

Bunun yerine, unix dönem UTC'sinden bu yana (tam olarak belgelenmiş) saniyelere ve istediğiniz anı elde etmek için bash aritmetiğine güvenebilirsiniz:

date -d @$(( $(date +"%s") - 24*3600)) +"%Y-%m-%d"

Bu başka bir cevapta belirtildi . Bu form, farklı datekomut satırı bayraklarına sahip platformlar arasında daha taşınabilir , dilden bağımsızdır (örneğin, Fransız yerelinde "dün" ve "hier") ve açıkçası (uzun vadede) hatırlanması daha kolay olacaktır, çünkü zaten biliyorum. Aksi halde kendinize şu soruyu sorabilirsiniz: "Öyle mi -d 2 hours agoyoksa -d 2 hour agotekrar mı?" veya "Öyle mi -d yesterdayyoksa -d 1 day agoistediğim mi?"). Burada sadece zor biraz @.

Bash ve başka bir şeyle silahlı:

Sadece bash üzerinde vurun, printf yerleşimi aracılığıyla dünün zamanını da alabilirsiniz:

 %(datefmt)T
     causes printf to output the date-time string resulting from using
     datefmt as a format string for strftime(3).  The  corresponding  argu
     ment  is an integer representing the number of seconds since the
     epoch.  Two special argument values may be used: -1 represents the
     current time, and -2 represents the time the shell was invoked.
     If no argument is specified, conversion behaves as if -1 had
     been  given.
     This is an exception to the usual printf behavior.

Yani,

# inner printf gets you the current unix time in seconds
# outer printf spits it out according to the format
printf "%(%Y-%m-%d)T\n" $(( $(printf "%(%s)T" -1) - 24*3600 ))

veya geçici bir değişkenle eşdeğerdir (dış alt kabuk isteğe bağlıdır, ancak ortamı temiz tutar).

(
  now=$(printf "%(%s)T" -1);
  printf "%(%Y-%m-%d)T\n" $((now - 24*3600));
)

Not: %()Tbiçimlendiriciye hiçbir argüman varsayılan kabul edemeyeceğini belirten manpage rağmen, -1onun yerine 0 olsun gibi görünüyor (teşekkür ederim, bash manuel sürüm 4.3.48)


0
date -d "yesterday" '+%Y-%m-%d'

Bunu daha sonra kullanmak için:

date=$(date -d "yesterday" '+%Y-%m-%d')

2
Bu kod OP sorununu çözse de, kodunuzun OP sorununu nasıl ele aldığına ilişkin bir açıklama eklemek daha iyidir. Bu şekilde, gelecekteki ziyaretçiler yayınınızdan öğrenebilir ve kendi kodlarına uygulayabilir. SO bir kodlama servisi değil, bilgi kaynağıdır. Yüksek kaliteli, eksiksiz cevaplar bu fikri pekiştirir ve daha yüksek bir olasılıkla onaylanır. Bu özellikler ve ayrıca tüm yayınların bağımsız olması şartıyla, bizi forumlardan ayıran bir platform olarak SO'nun güçlü yanlarıdır. Ek bilgi eklemek ve / veya açıklamalarınızı kaynak belgelerle desteklemek için düzenleyebilirsiniz.
SherylHohman

0

Kullanabilirsiniz:

date -d "yesterday 13:55" '+%Y-%m-%d'

Veya almak istediğiniz her zaman bash tarafından alınır.

Ay için:

date -d "30 days ago" '+%Y-%m-%d'

0

Bu soru etiketlendiğinden "DST güvenli"

Ve dateimplie gecikmesine komut vermek için çatal kullanarak, saf bash yerleşik kullanmanın basit ve daha verimli bir yolu vardır:

printf -v tznow '%(%z %s)T' -1
TZ=${tznow% *} printf -v yesterday '%(%Y-%m-%d)T' $(( ${tznow#* } - 86400 ))
echo $yesterday

Bu, çatallı olmaktan çok sistem dostu olarak çok daha hızlı için date.

itibaren V> = 5.0 , yeni bir değişken var$EPOCHSECONDS

printf -v tz '%(%z)T' -1
TZ=$tz printf -v yesterday '%(%Y-%m-%d)T' $(( EPOCHSECONDS - 86400 ))
echo $yesterday
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.