Công cụ trong UNIX để trừ ngày


22

Có công cụ nào trong Solaris UNIX (vì vậy không có công cụ GNU nào) để trừ ngày không? Tôi biết rằng trong Linux, chúng ta có gawkthể trừ đi một ngày từ một ngày khác. Nhưng ở Solaris, mức tối đa chúng ta có là nawk(được cải thiện awk) không thể thực hiện tính toán ngày. Ngoài ra tôi không thể sử dụng perl.

Có cách nào để tính ngày như thế 20100909 - 20001010nào không?

CẬP NHẬT: Có bcthể thực hiện tính toán ngày?


Câu trả lời:


10

Đây là một kịch bản awk tôi vừa viết, nên hoạt động với một awk POSIX. Bạn sẽ phải thử phiên bản Solaris; hãy nhớ rằng có hai phiên bản Awk trên Solaris, một trong / bin và một trong / usr / xpg4 / bin / awk (đó là nawk, tôi tin).

BEGIN {
    daysofmonth["01"] = 0; daysofmonth["02"] = 31; daysofmonth["03"] = 59;
    daysofmonth["04"] = 90; daysofmonth["05"] = 120; daysofmonth["06"] = 151;
    daysofmonth["07"] = 181; daysofmonth["08"] = 212; daysofmonth["09"] = 243;
    daysofmonth["10"] = 273; daysofmonth["11"] = 304; daysofmonth["12"] = 334;
    fullday = 86400;
}
/[12][09][0-9][0-9][01][0-9][0123][0-9]/ {
    year = substr($0, 1, 4); month = substr($0, 5, 2); day = substr($0, 7, 2);
    date = ((year - 1970) * 365.25) + daysofmonth[month] + day - 1;
    if ((year % 4) == 0 && month > 2) { date = date + 1; }
    print date * fullday - (25200);
}
{}

Vượt qua chuỗi ngày YYYYmmdd và nó sẽ được chuyển đổi thành số giây kể từ Kỷ nguyên (với một chút cho khi ở trên ranh giới ngày). Sau đó, bạn sẽ có thể trừ hai.

today=`echo 20110210 | awk -f convdate.awk`
then=`echo 20001231 | awk -f convdate.awk`
sincethen=`expr $today - $then`

Tôi đã kiểm tra logic của bạn với Oracle. Đối với một số ngày là ok, tuy nhiên đối với nó tạo ra một số float. Tôi sợ rằng tôi phải cắt bớt một số nguyên, phải không?
jyz

Số thập phân là phần của một giây và không nhất thiết cần thiết.
Arcege

Kỷ nguyên hết hạn 20380119. Tại sao không sử dụng ngày Julian trong năm? Dupe ... unix.stackexchange.com/questions/302266/ từ
jas-

13

Thật không may, không có tiện ích dòng lệnh POSIX nào cung cấp số học vào các ngày. date -ddate +%slà cách để đi nếu bạn có chúng, nhưng chúng là các phần mở rộng GNU.

Có một vụ hack vụng về với touchloại công việc đó để kiểm tra xem một ngày ít nhất là n ngày trong quá khứ:

touch -t 201009090000 stamp
if [ -n "$(find stamp -mtime +42)" ]; then ...

(Lưu ý rằng mã này có thể bị tắt bởi một nếu DST bắt đầu hoặc dừng trong khoảng thời gian và tập lệnh chạy trước 1 giờ sáng.)

Một số người đã kết thúc việc triển khai các thư viện thao tác ngày trong shell Bourne hoặc POSIX. Có một vài ví dụ và liên kết trong Câu hỏi thường gặp comp.unix.shell .

Cài đặt các công cụ GNU có thể là cách ít đau nhất.


11

Tôi sẽ thử sử dụng datelệnh là một phần của POSIX để nó có ở mọi nơi. CẬP NHẬT: Thật không may, có vẻ như -d không phải là một phần của ngày POSIX và có khả năng không có trên Solaris. Do đó, điều này có thể sẽ không trả lời câu hỏi OP.

d1=`date -d 20100909 +%s`
d2=`date -d 20001010 +%s`

Bây giờ d1d2là các số nguyên tương ứng với giây kể từ kỷ nguyên unix. Do đó, để có được sự khác biệt giữa hai loại, chúng tôi trừ ( $((d1-d2))trong bash) và chuyển đổi sang bất kỳ đơn vị nào chúng tôi muốn. Ngày là dễ nhất:

echo "$(((d1-d2)/86400)) days"

Cách thực hiện chuyển đổi có thể sẽ khác nếu bạn không có bash. Cách di động nhất có thể là sử dụng expr( trang man posix của expr ).


vâng, điều này không trả lời câu hỏi của tôi bởi vì đó là Solaris ... nhưng cảm ơn bạn vì đã ideia và đăng bài :)
jyz

8

Đối với hồ sơ, dateutils là nỗ lực của tôi trong việc cung cấp một bộ công cụ di động bao gồm mỹ phẩm ngày. Ví dụ của bạn sôi sùng sục

ddiff -i '%Y%m%d' 20001010 20100909
=>
  3621

Các -ichỉ định định dạng đầu vào.


2
Gói này là tuyệt vời và nó tồn tại trong các thư viện vũ trụ Ubuntu (ít nhất là cho Trusty). Trên một hệ thống khác, tôi có thể biên dịch nó dễ dàng từ đầu. Rat khuyen khich. Cảm ơn nhiều!
Robert Muil

Cũng được đóng gói trong Fedora và trong EPEL, cho hệ sinh thái RH.
mattdm

4

Perl có khả năng được cài đặt và đủ dễ dàng để lấy các mô-đun từ CPAN , cài đặt chúng trong thư mục chính của bạn và tham khảo chúng trong chương trình của bạn. Trong trường hợp này, mô-đun Date :: CalcDelta_Dayschương trình con sẽ giúp.


3

Ngày Wrt GNU trên Solaris:

Tôi nói điều này một lần nữa:

Quá nhiều Solaris SysAdmins tự hào khi không cố tình cài đặt các gói chính thức từ Sun (nay là Oracle) để tạo ra một hệ thống Solaris "tương thích GNU" khi họ định cấu hình máy chủ mới. Đánh bại tôi tại sao.

GNU Date là tuyệt vời và nên có sẵn theo mặc định trên bất kỳ máy chủ Solaris, IMHO.

Trên Solaris 10

Cài đặt gói SFWcoreu từ CD Solaris Companion. Sau khi cài đặt, bạn sẽ tìm thấy ngày GNU trong/opt/sfw/bin/date

Trên Solaris 11

Bạn có thể đã có nó vì tôi tin rằng nó là một phần của cài đặt tiêu chuẩn. Tuy nhiên, nó được gọi gdateđể phân biệt với phiên bản ngày của Mặt trời.

Làm điều này nếu không được cài đặt:

pkg cài đặt // solaris / file / gnu-coreutils

Cảm ơn vì tiền hỗ trợ. Bạn có thể cho tôi một ví dụ về cách sử dụng nó? Vì vậy, tôi có thể yêu cầu sysadmin cài đặt nó ...
jyz

Trên Solaris 11, nó sẽ được cài đặt thành cả hai /usr/bin/gdate/usr/gnu/bin/datevì vậy bạn có thể chọn sử dụng theo tên hoặc cài đặt $ PATH.
alanc

2

Nếu bạn có Python:

from time import *
date1 = strptime("20100909","%Y%m%d")
date2 = strptime("20001010","%Y%m%d")
diff = mktime(date1) - mktime(date2)
print repr(d/86400) + " days"

Bạn đã gắn thẻ câu hỏi của bạn "gawk" nhưng bạn nói "không có công cụ GNU". Gawk có số học ngày.


Tôi đã không. Ai đó đã chỉnh sửa bài đăng của tôi và được gắn thẻ "gawk" ...
jyz

2

trăn:

 from datetime import datetime as dt
 a = dt(2010, 9, 9)
 b = dt(2000, 10, 10)
 print (a - b).days

1

1. Xác định định dạng date1 và date2 trong %jngày của năm (001..366)

user@linux:~$ date1=`date -d 20100909 +%j` 
user@linux:~$ date2=`date -d 20001010 +%j`

2. Tính chênh lệch với expr

user@linux:~$ datediff=`expr $date2 - $date1`

3. Vì vậy, câu trả lời là 32 ngày

user@linux:~$ echo $datediff days
32 days
user@linux:~$ 

... hoặc Giải pháp một lớp lót

user@linux:~$ echo $(( $(date -d 20001010 +%j) - $(date -d 20100909 +%j) )) days
32 days
user@linux:~$ 

hoặc là

user@linux:~$ expr $(date -d 20001010 +%j) - $(date -d 20100909 +%j)
32
user@linux:~$

hoặc là

user@linux:~$ expr `date -d 20001010 +%j` - `date -d 20100909 +%j`
32
user@linux:~$ 

0

Với ngày BSD cho macOS:

echo "Quelle est la date de début ?"
read DATE_DE_DEBUT
echo "Quelle est la date de fin ?"
read DATE_DE_FIN
ANNEE=$(($(echo $DATE_DE_FIN | awk -F "/" '{print $3}')-$(echo $DATE_DE_DEBUT  | awk -F "/" '{print $3}')))

echo " "

if [[ $ANNEE > 0 ]]; then

for((annee=$ANNEE-1 ; $ANNEE ; annee++))

  do
  #echo $annee  
  for((mois=0 ; 13 - $mois ; mois++))
      do
  #   echo année:$annee mois:$mois
          for((jour=0 ; 32 - $jour ; jour++))
              do
 #             echo année:$annee mois:$mois jour:$jour
           TEST=$(date -Rjf"%d/%m/%Y" -v +"$annee"y -v +"$mois"m -v +"$jour"d $DATE_DE_DEBUT +"%d/%m/%Y")
           if [[ $TEST = $DATE_DE_FIN ]]; then
                  echo "Différence entre le $DATE_DE_DEBUT et le $DATE_DE_FIN";
                  echo "est de :";
                  echo "$annee année(s) $mois mois $jour jour(s)";
             exit 0;
            fi


          done 
  done
  done

 else 
 annee=0
 for((mois=0 ; 13 - $mois ; mois++))
      do
#      echo année:$annee mois:$mois
          for((jour=0 ; 32 - $jour ; jour++))
              do
              #echo année:$annee mois:$mois jour:$jour
              TEST=$(date -Rjf"%d/%m/%Y" -v +"$annee"y -v +"$mois"m -v +"$jour"d $DATE_DE_DEBUT +"%d/%m/%Y")
              if [[ $TEST = $DATE_DE_FIN ]]; then 
                      echo "Différence entre le $DATE_DE_DEBUT et le $DATE_DE_FIN";
                     echo "est de :";
                     echo "$annee année(s) $mois mois $jour jour(s)";
              exit 0;
              fi
              done
      done

fi

0

Bạn có thể sử dụng thư viện Vk awk để trả về sự khác biệt trong vài giây:

$ velour -n 'print t_utc(2010, 9, 9) - t_utc(2000, 10, 10)'
312854400

Hoặc ngày:

$ velour -n 'print t_secday(t_utc(2010, 9, 9) - t_utc(2000, 10, 10))'
3621
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.