簡體   English   中英

Bash - 給定日期的小時數

[英]Bash - number of hours in given day

在 Linux 上使用 Bash shell,並給定日期時間,我如何確定那一天有多少小時?

日期時間與某些具有夏令時的時區有關,例如 MET。

為了完全考慮所有場景,您需要考慮以下幾點:

  • 並非每個本地日都有午夜,如果您在這些日子之一傳遞日期,則date命令將失敗,除非您還傳遞了時間和與 UTC 的偏移量。 這主要發生在春季向前的過渡日。 例如:

     $ TZ=America/Sao_Paulo date -d '2016-10-16' date: invalid date '2016-10-16'
  • 並非每個 DST 過渡都是 1 小時。 America/Lord_Howe切換 30 分鍾。 Bash 只執行整數除法,所以如果你想要小數,你必須使用這些技術之一

這是一個解釋這些的函數:

seconds_in_day() {
  # Copy input date to local variable
  date=$1

  # Start with the offset at noon on the given date.
  # Noon will almost always exist (except Samoa on 2011-12-30)
  offset1=$(date -d "$date 12:00" +%z)

  # Next get the offset for midnight.  If it doesn't exist, the time will jump back to 23:00 and we'll get a different offset.
  offset1=$(date -d "$date 00:00 $offset1" +%z)

  # Next get the offset for the next day at midnight.  Again, if it doesn't exist, it will jump back an hour.
  offset2=$(date -d "$date 00:00 $offset1 + 1 day" +%z)

  # Get the unix timestamps for both the current date and the next one, at midnight with their respective offsets.
  unixtime1=$(date -d "$date 00:00 $offset1" +%s)
  unixtime2=$(date -d "$date 00:00 $offset2 + 1 day" +%s)

  # Calculate the difference in seconds and hours.  Use awk for decimal math.
  seconds=$((unixtime2 - unixtime1))
  hours=$(awk -v seconds=$seconds 'BEGIN { print seconds / 3600 }')

  # Print the output
  echo "$date had $seconds secs in $TZ, or $hours hours."
}

例子:

$ TZ=America/Los_Angeles seconds_in_day 2016-03-12
2016-03-12 had 86400 secs in America/Los_Angeles, or 24 hours.
$ TZ=America/Los_Angeles seconds_in_day 2016-03-13
2016-03-13 had 82800 secs in America/Los_Angeles, or 23 hours.
$ TZ=America/Los_Angeles seconds_in_day 2016-03-14
2016-03-14 had 86400 secs in America/Los_Angeles, or 24 hours.

$ TZ=America/Los_Angeles seconds_in_day 2016-11-05
2016-11-05 had 86400 secs in America/Los_Angeles, or 24 hours.
$ TZ=America/Los_Angeles seconds_in_day 2016-11-06
2016-11-06 had 90000 secs in America/Los_Angeles, or 25 hours.
$ TZ=America/Los_Angeles seconds_in_day 2016-11-07
2016-11-07 had 86400 secs in America/Los_Angeles, or 24 hours.

$ TZ=America/Sao_Paulo seconds_in_day 2016-02-19
2016-02-19 had 86400 secs in America/Sao_Paulo, or 24 hours.
$ TZ=America/Sao_Paulo seconds_in_day 2016-02-20
2016-02-20 had 90000 secs in America/Sao_Paulo, or 25 hours.
$ TZ=America/Sao_Paulo seconds_in_day 2016-02-21
2016-02-21 had 86400 secs in America/Sao_Paulo, or 24 hours.

$ TZ=America/Sao_Paulo seconds_in_day 2016-10-15
2016-10-15 had 86400 secs in America/Sao_Paulo, or 24 hours.
$ TZ=America/Sao_Paulo seconds_in_day 2016-10-16
2016-10-16 had 82800 secs in America/Sao_Paulo, or 23 hours.
$ TZ=America/Sao_Paulo seconds_in_day 2016-10-17
2016-10-17 had 86400 secs in America/Sao_Paulo, or 24 hours.

$ TZ=Australia/Lord_Howe seconds_in_day 2016-04-02
2016-04-02 had 86400 secs in Australia/Lord_Howe, or 24 hours.
$ TZ=Australia/Lord_Howe seconds_in_day 2016-04-03
2016-04-03 had 88200 secs in Australia/Lord_Howe, or 24.5 hours.
$ TZ=Australia/Lord_Howe seconds_in_day 2016-04-04
2016-04-04 had 86400 secs in Australia/Lord_Howe, or 24 hours.

$ TZ=Australia/Lord_Howe seconds_in_day 2016-10-01
2016-10-01 had 86400 secs in Australia/Lord_Howe, or 24 hours.
$ TZ=Australia/Lord_Howe seconds_in_day 2016-10-02
2016-10-02 had 84600 secs in Australia/Lord_Howe, or 23.5 hours.
$ TZ=Australia/Lord_Howe seconds_in_day 2016-10-03
2016-10-03 had 86400 secs in Australia/Lord_Howe, or 24 hours.

10 月 30 日是英國最后一個夏令時。 我可以通過這種方式從 shell 獲得那天的 25 小時:

t1=$(TZ='Europe/London' date --date='20161030' +%s)
t2=$(TZ='Europe/London' date --date='20161031' +%s)
echo $((($t2 - $t1) / 3600))

我不完全確定這會在每個 bash shell 中工作,並且可能需要稍微調整一下。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM