เครื่องมือใน UNIX เพื่อลบวันที่


22

มีเครื่องมือใดใน Solaris UNIX (ดังนั้นจึงไม่มีเครื่องมือ GNU) เพื่อลบวันที่หรือไม่ ฉันรู้ว่าใน Linux เรามีgawkที่สามารถลบหนึ่งวันจากที่อื่น แต่ใน Solaris ค่าสูงสุดที่เรามีคือnawk(ปรับปรุงawk) ซึ่งไม่สามารถทำการคำนวณวันที่ได้ นอกจากนี้ฉันไม่สามารถใช้ Perl

มีวิธีใดในการคำนวณวันที่เป็น20100909 - 20001010อย่างไร

อัปเดต: bcสามารถคำนวณวันที่ได้หรือไม่


คำตอบ:


10

นี่คือสคริปต์ awk ที่ฉันเพิ่งเขียนขึ้นควรทำงานกับ POSIX awk คุณจะต้องลองเวอร์ชัน Solaris โปรดจำไว้ว่ามี Awk สองรุ่นใน Solaris เช่นกันหนึ่งใน / bin และอีกหนึ่งใน / usr / xpg4 / bin / awk (ซึ่งเป็น nawk ฉันเชื่อว่า)

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);
}
{}

ส่งผ่านสตริงวันที่ YYYYmmdd ผ่านและมันจะถูกแปลงเป็นจำนวนวินาทีนับตั้งแต่ยุค (ด้วยการให้เล็กน้อยสำหรับการอยู่ในขอบเขตวัน) จากนั้นคุณจะสามารถลบทั้งสอง

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

ฉันตรวจสอบตรรกะของคุณด้วย Oracle สำหรับบางวันก็โอเค แต่มันจะสร้างจำนวนลอย ฉันเกรงว่าฉันจะต้องตัดทอนเป็นจำนวนเต็มจริงไหม?
jyz

ทศนิยมคือเศษส่วนของวินาทีและไม่จำเป็นต้องใช้
Arcege

ยุคหมดอายุ 20380119 ทำไมไม่ใช้วันจูเลียนแห่งปี? Dupe ... unix.stackexchange.com/questions/302266/…
jas-

13

น่าเสียดายที่ไม่มีโปรแกรมอรรถประโยชน์บรรทัดคำสั่ง POSIX ให้การคำนวณในวันที่ date -dและdate +%sเป็นหนทางที่จะไปหากคุณมี แต่เป็นส่วนขยายของ GNU

มีแฮ็คที่เงอะงะกับการtouchเรียงลำดับของงานเพื่อตรวจสอบว่าวันที่อย่างน้อย n วันในอดีตที่ผ่านมา:

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

(โปรดทราบว่ารหัสนี้อาจถูกปิดโดยหนึ่งถ้า DST เริ่มต้นหรือหยุดในช่วงเวลาและสคริปต์ทำงานก่อน 1:00)

หลายคนลงเอยด้วยการติดตั้งไลบรารีการจัดการวันที่ในเชลล์เป้าหมายหรือ POSIX มีไม่กี่ตัวอย่างและการเชื่อมโยงในมีcomp.unix.shell คำถามที่พบบ่อย

การติดตั้งเครื่องมือ GNU อาจเป็นวิธีที่เจ็บปวดน้อยที่สุด


11

ฉันจะลองใช้dateคำสั่งซึ่งเป็นส่วนหนึ่งของ POSIX ดังนั้นมันเกือบทุกที่ อัปเดต: น่าเสียดายที่ดูเหมือนว่า -d ไม่ได้เป็นส่วนหนึ่งของวันที่ POSIX และน่าจะไม่มีใน Solaris ดังนั้นสิ่งนี้อาจจะไม่ตอบคำถาม OPs

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

ตอนนี้d1และd2เป็นจำนวนเต็มที่สอดคล้องกับวินาทีตั้งแต่ unix epoch ดังนั้นเพื่อให้ได้ความแตกต่างระหว่างสองเราจะลบ ( $((d1-d2))ใน bash) และแอบแฝงกับหน่วยใด ๆ ที่เราต้องการ วันง่ายที่สุด:

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

วิธีการแปลงน่าจะแตกต่างกันถ้าคุณไม่มีทุบตี วิธีที่พกพาได้มากที่สุดคือการใช้expr( หน้า posix ของ expr )


ใช่สิ่งนี้ไม่ตอบคำถามของฉันเพราะมันเป็นโซลาริส ... แต่ขอบคุณสำหรับ ideia และโพสต์ :)
jyz

8

สำหรับการบันทึกdateutilsเป็นความพยายามของฉันในการจัดหาชุดเครื่องมือพกพาที่ครอบคลุมวันที่ทางคณิตศาสตร์ ตัวอย่างของคุณเดือดลงไป

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

-iระบุรูปแบบการป้อนข้อมูล


2
แพ็คเกจนี้ยอดเยี่ยมและมีอยู่ในห้องสมุดจักรวาลของ Ubuntu (อย่างน้อยก็สำหรับ Trusty) ในอีกระบบหนึ่งฉันสามารถรวบรวมได้อย่างง่ายดายตั้งแต่เริ่มต้น แนะนำเป็นอย่างยิ่ง ขอบคุณมาก!
Robert Muil

บรรจุใน Fedora และ EPEL สำหรับระบบนิเวศ RH ด้วย
mattdm

4

Perl มีแนวโน้มที่จะถูกติดตั้งและมันง่ายพอที่จะรับโมดูลจากCPANติดตั้งในโฮมไดเร็กตอรี่ของคุณและอ้างอิงถึงพวกมันในโปรแกรมของคุณ ในกรณีนี้โมดูลDate :: CalcมีDelta_Daysรูทีนย่อยที่จะช่วย


3

Wrt GNU date บน Solaris:

ฉันพูดแบบนี้อีกครั้ง:

Solaris SysAdmins จำนวนมากเกินไปมีความภาคภูมิใจในการไม่ติดตั้งแพ็คเกจอย่างเป็นทางการจาก Sun (ตอนนี้ Oracle) ที่ทำให้ระบบ Solaris "GNU ใช้งานร่วมกันได้" เมื่อตั้งค่าโฮสต์ใหม่ ทำไมฉัน

วันที่ของ GNU นั้นยอดเยี่ยมและควรจะมีอยู่ในโฮสต์ Solaris ใด ๆ โดยปริยาย

บน Solaris 10

ติดตั้งแพคเกจ SFWcoreu จากแผ่นซีดี Solaris Companion หลังจากติดตั้งแล้วคุณจะพบวันที่ของ GNU/opt/sfw/bin/date

บน Solaris 11

คุณอาจมีอยู่แล้วเพราะฉันเชื่อว่าเป็นส่วนหนึ่งของการติดตั้งมาตรฐาน อย่างไรก็ตามมีการเรียกใช้gdateเพื่อแยกความแตกต่างจากวันที่ในเวอร์ชัน Sun

ทำเช่นนี้หากไม่ได้ติดตั้ง:

pkg install // solaris / file / gnu-coreutils

ขอบคุณสำหรับทิป. คุณช่วยยกตัวอย่างวิธีการใช้ให้ฉันได้ไหม ดังนั้นผมจึงสามารถขอให้ดูแลระบบการติดตั้งมัน ...
jyz

บน Solaris 11 นั้นจะถูกติดตั้งเป็นทั้งคู่/usr/bin/gdateและ/usr/gnu/bin/dateคุณสามารถเลือกใช้ทั้งตามชื่อหรือตามการตั้งค่า $ PATH
alanc

2

ถ้าคุณมีงูหลาม:

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"

คุณติดแท็กคำถามของคุณ "เพ่งพิศ" แต่คุณพูดว่า "ไม่มีเครื่องมือ GNU" Gawk มีเลขคณิตวันที่


ฉันไม่ได้ มีคนแก้ไขโพสต์ของฉันและติดแท็ก "gawk" ...
jyz


1

1. กำหนดวันที่ 1 และวันที่ 2 ใน%jรูปแบบของวันที่ปี (001..366)

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

2. คำนวณความแตกต่างด้วย expr

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

3. ดังนั้นคำตอบคือ 32 วัน

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

... หรือโซลูชัน One-liner

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

หรือ

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

หรือ

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

0

ด้วยวันที่ BSD สำหรับ 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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.