বাশ স্ক্রিপ্টে সময় কাটানোর জন্য কীভাবে?


224

আমি শুরু এবং শেষ সময়টি ব্যবহার করে মুদ্রণ করি date +"%T", যার ফলস্বরূপ এমন কিছু ঘটে:

10:33:56
10:36:10

আমি কীভাবে এই দুটিয়ের মধ্যে পার্থক্য গণনা করতে এবং মুদ্রণ করতে পারি?

আমি কিছু পেতে চাই:

2m 14s

5
অন্য নোটে, আপনি timeকমান্ডটি ব্যবহার করতে পারবেন না ?
আনিসনে

পরিবর্তে ইউনিক্স সময় ব্যবহার করুন date +%s, তারপরে কয়েক সেকেন্ডের মধ্যে পার্থক্য পেতে বিয়োগ করুন।
রোব্লোগিক

উত্তর:


476

বাশের একটি কার্যকর SECONDSবিল্টিন ভেরিয়েবল রয়েছে যা শেল শুরুর পর থেকে কত সেকেন্ড পেরিয়ে গেছে তা ট্র্যাক করে। এই ভেরিয়েবলটি নির্ধারিত হওয়ার পরে তার বৈশিষ্ট্যগুলি ধরে রাখে এবং অ্যাসাইনমেন্টের পরে প্রদত্ত মানটি অ্যাসাইনমেন্ট প্লাস হিসাবে নির্ধারিত মানের পরে সেকেন্ডের সংখ্যা।

সুতরাং, SECONDSসময় নির্ধারিত ইভেন্ট শুরু করার আগে আপনি কেবল 0 এ সেট করতে পারেন, ইভেন্টের SECONDSপরে কেবল পড়তে পারেন , এবং প্রদর্শনের আগে সময় গাণিতিক করতে পারেন।

SECONDS=0
# do some work
duration=$SECONDS
echo "$(($duration / 60)) minutes and $(($duration % 60)) seconds elapsed."

যেহেতু এই সমাধানটি নির্ভর করে না date +%s(যা একটি জিএনইউ এক্সটেনশন), এটি বাশ সমর্থিত সমস্ত সিস্টেমে বহনযোগ্য।


59
+1 টি। উল্লেখ্য, আপনাকে প্রতারিত করতে date, আপনার জন্য সময় গাণিতিক করণ লিখে মধ্যে date -u -d @"$diff" +'%-Mm %-Ss'। (এটি $diffযুগের দ্বিতীয় সেকেন্ড হিসাবে ব্যাখ্যা করে এবং ইউটিসিতে কয়েক মিনিট এবং সেকেন্ড গণনা করে)) এটি সম্ভবত আরও মার্জিত নয়, যদিও এটি আরও ভালভাবে অবহেলিত। :
পি

13
সুন্দর এবং সহজ। কারও যদি ঘন্টা দরকার হয়:echo "$(($diff / 3600)) hours, $((($diff / 60) % 60)) minutes and $(($diff % 60)) seconds elapsed."

6
$(date -u +%s)দিবালোকের সময় সাশ্রয় করার সময়টি পরিবর্তিত হয় এমন তারিখে রেস শর্ত রোধ করতে এটি পড়া উচিত । এবং অশুভ লিপ সেকেন্ড থেকে সাবধান থাকুন;)
টিনো

3
@ ড্যানিয়েল-কামিল-কোজার ভাল লাগবে। তবে এটি কিছুটা নাজুক। এর মধ্যে একটি মাত্র পরিবর্তনশীল, তাই এটি সঞ্চালনের পরে কর্মক্ষমতা পরিমাপ করার জন্য এবং unset SECONDSএটি আরও খারাপতর হিসাবে পুনরাবৃত্তভাবে ব্যবহার করা যায় না:echo $SECONDS; unset SECONDS; SECONDS=0; sleep 3; echo $SECONDS
টিনো

6
@ পার্থিয়ানশট: আপনারা এমনটি ভাবেন বলে আমি দুঃখিত। যাইহোক, আমি বিশ্বাস করি যে এই প্রশ্নের উত্তরগুলির সন্ধান করার সময় বেশিরভাগ লোকদের এই উত্তরটি প্রয়োজন: সময় গণনা না করে ইভেন্টগুলির মধ্যে কতটা সময় কেটে গেছে তা পরিমাপ করা।
ড্যানিয়েল কামিল কোজার

99

সেকেন্ড

অতিবাহিত সময় পরিমাপ করতে (সেকেন্ডে) আমাদের প্রয়োজন:

  • একটি পূর্ণসংখ্যা যা অতিবাহিত সেকেন্ড এবং এর গণনা উপস্থাপন করে
  • যেমন পূর্ণসংখ্যাকে একটি ব্যবহারযোগ্য বিন্যাসে রূপান্তর করার উপায়।

অতিবাহিত সেকেন্ডের একটি পূর্ণসংখ্যা মান:

  • অতিবাহিত সেকেন্ডের সংখ্যার জন্য একটি পূর্ণসংখ্যার মান সন্ধানের জন্য দুটি বাশ অভ্যন্তরীণ উপায় রয়েছে:

    1. ভেরিয়েবল ভেরিয়েবল SECONDS (যদি SECONDS সেট না করা থাকে তবে এটি তার বিশেষ সম্পত্তি হারাবে)।

      • SECONDS এর মান 0 তে নির্ধারণ করা হচ্ছে:

        SECONDS=0
        sleep 1  # Process to execute
        elapsedseconds=$SECONDS
        
      • SECONDSশুরুতে ভেরিয়েবলের মান সংরক্ষণ করা :

        a=$SECONDS
        sleep 1  # Process to execute
        elapsedseconds=$(( SECONDS - a ))
        
    2. বাশ প্রিন্টফ বিকল্প %(datefmt)T:

      a="$(TZ=UTC0 printf '%(%s)T\n' '-1')"    ### `-1`  is the current time
      sleep 1                                  ### Process to execute
      elapsedseconds=$(( $(TZ=UTC0 printf '%(%s)T\n' '-1') - a ))
      

এই জাতীয় পূর্ণসংখ্যাকে একটি ব্যবহারযোগ্য বিন্যাসে রূপান্তর করুন

ব্যাশ অভ্যন্তরীণ printfসরাসরি এটি করতে পারে:

$ TZ=UTC0 printf '%(%H:%M:%S)T\n' 12345
03:25:45

একভাবে

$ elapsedseconds=$((12*60+34))
$ TZ=UTC0 printf '%(%H:%M:%S)T\n' "$elapsedseconds"
00:12:34

তবে এটি 24 ঘন্টােরও বেশি সময়কালের জন্য ব্যর্থ হবে, কারণ আমরা আসলে কোনও দেয়ালের ঘড়ির সময় মুদ্রণ করি, সত্যিকার অর্থে কোনও সময়কাল নয়:

$ hours=30;mins=12;secs=24
$ elapsedseconds=$(( ((($hours*60)+$mins)*60)+$secs ))
$ TZ=UTC0 printf '%(%H:%M:%S)T\n' "$elapsedseconds"
06:12:24

বিশদ প্রেমীদের জন্য, বাশ-হ্যাকারস.আর্গ.এ. থেকে :

%(FORMAT)Tফরমেট এর জন্য বিন্যাসের স্ট্রিং হিসাবে ব্যবহারের ফলে তারিখ-সময়ের স্ট্রিং আউটপুট করে strftime(3)। সম্পর্কিত আর্গুমেন্টটি ইপোক , বা -1 (বর্তমান সময়) বা -2 (শেল প্রারম্ভকালীন সময়) থেকে সেকেন্ডের সংখ্যা । যদি কোনও সম্পর্কিত যুক্তি সরবরাহ না করা হয় তবে বর্তমান সময়টি ডিফল্ট হিসাবে ব্যবহৃত হয়।

সুতরাং আপনি কেবল কল করতে চাইতে পারেন textifyDuration $elpasedsecondsযেখানে আরও textifyDurationএকটি সময়কাল মুদ্রণের বাস্তবায়ন রয়েছে:

textifyDuration() {
   local duration=$1
   local shiff=$duration
   local secs=$((shiff % 60));  shiff=$((shiff / 60));
   local mins=$((shiff % 60));  shiff=$((shiff / 60));
   local hours=$shiff
   local splur; if [ $secs  -eq 1 ]; then splur=''; else splur='s'; fi
   local mplur; if [ $mins  -eq 1 ]; then mplur=''; else mplur='s'; fi
   local hplur; if [ $hours -eq 1 ]; then hplur=''; else hplur='s'; fi
   if [[ $hours -gt 0 ]]; then
      txt="$hours hour$hplur, $mins minute$mplur, $secs second$splur"
   elif [[ $mins -gt 0 ]]; then
      txt="$mins minute$mplur, $secs second$splur"
   else
      txt="$secs second$splur"
   fi
   echo "$txt (from $duration seconds)"
}

জিএনইউ তারিখ।

গঠনের সময় পেতে আমাদের প্রায় এক বছরের দৈর্ঘ্য এবং ন্যানোসেকেন্ড সহ বেশ কয়েকটি উপায়ে একটি বাহ্যিক সরঞ্জাম (জিএনইউ তারিখ) ব্যবহার করা উচিত।

তারিখের ভিতরে গণিত।

বাহ্যিক গাণিতিকের কোনও প্রয়োজন নেই, এটি সমস্ত ভিতরে এক ধাপে করুন date:

date -u -d "0 $FinalDate seconds - $StartDate seconds" +"%H:%M:%S"

হ্যাঁ, 0কমান্ড স্ট্রিংয়ে একটি শূন্য রয়েছে। এটি দরকার.

এটি ধরে নিয়েছে যে আপনি date +"%T"কমান্ডকে কমান্ডে পরিবর্তন করতে পারেন date +"%s"তাই মানগুলি সেকেন্ডে সংরক্ষণ করা (মুদ্রিত) হয়ে যাবে।

লক্ষ্য করুন যে কমান্ডটি সীমাবদ্ধ:

  • $StartDateএবং $FinalDateসেকেন্ডের ইতিবাচক মান ।
  • এর মান এর $FinalDateচেয়ে বড় (পরে সময়ে) $StartDate
  • সময়ের পার্থক্য 24 ঘন্টাের চেয়ে ছোট।
  • আপনি ঘন্টা, মিনিট এবং সেকেন্ডের সাথে একটি আউটপুট ফর্ম্যাট গ্রহণ করেন। পরিবর্তন করা খুব সহজ।
  • এটি ইউটিসি বারের জন্য গ্রহণযোগ্য। "ডিএসটি" এবং স্থানীয় সময় সংশোধন এড়াতে।

আপনার যদি স্ট্রিংটি অবশ্যই ব্যবহার করা উচিত তবে 10:33:56ভাল, কেবল এটি সেকেন্ডে রূপান্তর করুন, সেকেন্ডে
শব্দটি সেকেন্ড হিসাবে সংক্ষেপিত হতে পারে:

string1="10:33:56"
string2="10:36:10"
StartDate=$(date -u -d "$string1" +"%s")
FinalDate=$(date -u -d "$string2" +"%s")
date -u -d "0 $FinalDate sec - $StartDate sec" +"%H:%M:%S"

নোট করুন যে সেকেন্ডের সময় রূপান্তর (উপরে উপস্থাপিত হিসাবে) "এই" দিন (আজ) শুরুর সাথে সম্পর্কিত।


এই ধারণাটি ন্যানোসেকেন্ডগুলিতে প্রসারিত হতে পারে:

string1="10:33:56.5400022"
string2="10:36:10.8800056"
StartDate=$(date -u -d "$string1" +"%s.%N")
FinalDate=$(date -u -d "$string2" +"%s.%N")
date -u -d "0 $FinalDate sec - $StartDate sec" +"%H:%M:%S.%N"

যদি দীর্ঘ পার্থক্য (364 দিন অবধি) সময়ের পার্থক্য গণনা করতে হয় তবে আমাদের অবশ্যই (কিছু) বছরের সূচনা হিসাবে উল্লেখ করতে হবে এবং ফর্ম্যাট মান %j(বছরের দিন সংখ্যা):

অনুরূপ, একই, সমতুল্য:

string1="+10 days 10:33:56.5400022"
string2="+35 days 10:36:10.8800056"
StartDate=$(date -u -d "2000/1/1 $string1" +"%s.%N")
FinalDate=$(date -u -d "2000/1/1 $string2" +"%s.%N")
date -u -d "2000/1/1 $FinalDate sec - $StartDate sec" +"%j days %H:%M:%S.%N"

Output:
026 days 00:02:14.340003400

দুঃখের বিষয়, 1এক্ষেত্রে আমাদের কয়েক দিনের সংখ্যা থেকে ম্যানুয়ালি বিয়োগ করতে হবে । তারিখের কমান্ড বছরের প্রথম দিনটিকে 1 হিসাবে দেখায় that এমনটি কঠিন নয় ...

a=( $(date -u -d "2000/1/1 $FinalDate sec - $StartDate sec" +"%j days %H:%M:%S.%N") )
a[0]=$((10#${a[0]}-1)); echo "${a[@]}"



দীর্ঘ সংখ্যক সেকেন্ডের ব্যবহার বৈধ এবং এখানে নথিভুক্ত: https://www.gnu.org/software/coreutils/manual/html_node/ উদাহরণ-of-date.html#
উদাহরণস্বরূপ- তারিখ


ব্যস্তবক্সের তারিখ

ছোট ডিভাইসে ব্যবহৃত একটি সরঞ্জাম (ইনস্টল করার জন্য খুব ছোট এক্সিকিউটেবল): ব্যুসিবক্স।

হয় ব্যস্তবক্সের তারিখ নামে একটি লিঙ্ক তৈরি করুন:

$ ln -s /bin/busybox date

এটির পরে কল করে এটি ব্যবহার করুন date(এটিকে একটি PATH অন্তর্ভুক্ত ডিরেক্টরিতে রাখুন)।

বা এর মতো একটি নাম তৈরি করুন:

$ alias date='busybox date'

ব্যাসবক্সের তারিখটিতে একটি দুর্দান্ত বিকল্প রয়েছে: -ডি ইনপুট সময়ের ফর্ম্যাটটি পেতে। এটি সময় হিসাবে ব্যবহৃত হতে অনেক ফর্ম্যাট খোলে। -D বিকল্পটি ব্যবহার করে আমরা সময়কে 10:33:56 সরাসরি রূপান্তর করতে পারি:

date -D "%H:%M:%S" -d "10:33:56" +"%Y.%m.%d-%H:%M:%S"

এবং উপরের কমান্ডের আউটপুট থেকে আপনি দেখতে পাচ্ছেন যে দিনটি "আজ" হিসাবে ধরে নেওয়া হবে। যুগের শুরু থেকে সময় পেতে:

$ string1="10:33:56"
$ date -u -D "%Y.%m.%d-%H:%M:%S" -d "1970.01.01-$string1" +"%Y.%m.%d-%H:%M:%S"
1970.01.01-10:33:56

ব্যাসবক্সের তারিখ এমনকি সময়টি (উপরের ফর্ম্যাটে) -ডি ছাড়াই পেতে পারে:

$ date -u -d "1970.01.01-$string1" +"%Y.%m.%d-%H:%M:%S"
1970.01.01-10:33:56

এবং আউটপুট ফর্ম্যাট পর্বের আগে থেকে কয়েক সেকেন্ডও হতে পারে।

$ date -u -d "1970.01.01-$string1" +"%s"
52436

উভয় সময়, এবং একটি সামান্য বাশ গণিত (ব্যস্তবক্স এখনও গণিত করতে পারে না):

string1="10:33:56"
string2="10:36:10"
t1=$(date -u -d "1970.01.01-$string1" +"%s")
t2=$(date -u -d "1970.01.01-$string2" +"%s")
echo $(( t2 - t1 ))

বা বিন্যাসিত:

$ date -u -D "%s" -d "$(( t2 - t1 ))" +"%H:%M:%S"
00:02:14

6
এটি এমন আশ্চর্যজনক উত্তরটি অনেকগুলি ঘাঁটি এবং সূক্ষ্ম ব্যাখ্যার সাথে আবৃত। ধন্যবাদ!
ডেভি

আমাকে বাশকে সংহত কমান্ডের %(FORMAT)Tকাছে দেওয়া স্ট্রিংটি দেখতে হয়েছিল printfBash-hackers.org থেকে : স্ট্রাইফটাইমের (3) ফর্ম্যাট স্ট্রিং হিসাবে %(FORMAT)Tব্যবহারের ফলে ডেট-টাইম স্ট্রিং আউটপুট দেয় FORMAT। সম্পর্কিত আর্গুমেন্টটি ইপোক, বা -1 (বর্তমান সময়) বা -2 (শেল প্রারম্ভকালীন সময়) থেকে সেকেন্ডের সংখ্যা। যদি কোনও সম্পর্কিত যুক্তি সরবরাহ না করা হয় তবে বর্তমান সময়টি ডিফল্ট হিসাবে ব্যবহৃত হয় । এটি রহস্যজনক। এই ক্ষেত্রে, %sদেওয়া হিসাবে strftime(3)"যুগের পর থেকে সেকেন্ডের সংখ্যা"।
ডেভিড টনহোফার 26'18

35

আমি এটি কীভাবে করেছি তা এখানে:

START=$(date +%s);
sleep 1; # Your stuff
END=$(date +%s);
echo $((END-START)) | awk '{print int($1/60)":"int($1%60)}'

সত্যিই সহজ, শুরুতে সেকেন্ডের সংখ্যাটি নিন, তারপরে শেষে সেকেন্ডের সংখ্যাটি নিন এবং কয়েক মিনিটের মধ্যে পার্থক্যটি মুদ্রণ করুন: সেকেন্ডে।


6
কীভাবে এটি আমার সমাধান থেকে আলাদা? awkএই ক্ষেত্রে ফোন করে আমি সত্যিই সুবিধাটি দেখতে পাচ্ছি না , যেহেতু বাশ পূর্ণসংখ্যার অঙ্কটি সমানভাবে পরিচালনা করে।
ড্যানিয়েল কামিল কোজার

1
আপনার উত্তরটিও সঠিক। আমার মতো কিছু লোক ব্যাশের অসঙ্গতিগুলির চেয়ে বাজেটের সাথে কাজ করতে পছন্দ করে।
ডোরিয়ান

2
আপনি সংখ্যার পাটিগণিত সম্পর্কিত বাশের অসঙ্গতি সম্পর্কে আরও কিছু ব্যাখ্যা করতে পারেন? আমি এই সম্পর্কে আরও জানতে চাই, যেহেতু আমি কারও সম্পর্কে অবগত ছিলাম না।
ড্যানিয়েল কামিল কোজার

12
আমি শুধু এটি খুঁজছিলাম। আমি এই উত্তরের সমালোচনা বুঝতে পারি না। আমি একটি সমস্যার একাধিক সমাধান দেখতে চাই। এবং, আমি এমন একজন যা awkব্যাশ করার আদেশগুলি পছন্দ করে (যদি অন্য কোনও কিছু না করে, কারণ এভাক অন্যান্য শেলগুলিতে কাজ করে)। আমি এই সমাধানটি আরও ভাল পছন্দ করেছি। তবে এটি আমার ব্যক্তিগত মতামত।
আরপিএসএমএল

4
শীর্ষস্থানীয় শূন্যগুলি: প্রতিধ্বনি $ ((END-START)) | awk '{printf "% 02d:% 02d \ n", int ($ 1/60), int ($ 1% 60)}'
জন স্ট্রেয়ার

17

আরেকটি বিকল্প ব্যবহার করা datediffথেকে dateutils( http://www.fresse.org/dateutils/#datediff ):

$ datediff 10:33:56 10:36:10
134s
$ datediff 10:33:56 10:36:10 -f%H:%M:%S
0:2:14
$ datediff 10:33:56 10:36:10 -f%0H:%0M:%0S
00:02:14

আপনি ব্যবহার করতে পারে gawkmawk1.3.4 এছাড়াও আছে strftimeএবং mktimeকিন্তু তার থেকে বড় সংস্করণ mawkএবং nawkনা।

$ TZ=UTC0 awk 'BEGIN{print strftime("%T",mktime("1970 1 1 10 36 10")-mktime("1970 1 1 10 33 56"))}'
00:02:14

বা জিএনইউ দিয়ে এটি করার আরও একটি উপায় এখানে রয়েছে date:

$ date -ud@$(($(date -ud'1970-01-01 10:36:10' +%s)-$(date -ud'1970-01-01 10:33:56' +%s))) +%T
00:02:14

1
আমি আপনার জিএনইউ date পদ্ধতির মতো কিছু খুঁজছিলাম । জিনিয়াস।
হাওহামারু

দয়া করে আমার মন্তব্য মুছুন ... দুঃখিত
বিল গালে

অ্যাপের dateutilsমাধ্যমে ইনস্টল করার পরে , কোনও datediffআদেশ ছিল না - ব্যবহার করতে হয়েছিল dateutils.ddiff
সুজানা

12

আমি অন্য কোনও উপায়ে প্রস্তাব করতে চাই যাতে dateকমান্ড পুনরায় কল করা এড়ানো যায় । আপনি যদি ইতিমধ্যে %Tতারিখের ফর্ম্যাটে টাইমস্ট্যাম্পগুলি সংগ্রহ করে থাকেন তবে এটি ক্ষেত্রে সহায়ক হতে পারে :

ts_get_sec()
{
  read -r h m s <<< $(echo $1 | tr ':' ' ' )
  echo $(((h*60*60)+(m*60)+s))
}

start_ts=10:33:56
stop_ts=10:36:10

START=$(ts_get_sec $start_ts)
STOP=$(ts_get_sec $stop_ts)
DIFF=$((STOP-START))

echo "$((DIFF/60))m $((DIFF%60))s"

আমরা এমনকি একইভাবে মিলিসেকেন্ডগুলি পরিচালনা করতে পারি।

ts_get_msec()
{
  read -r h m s ms <<< $(echo $1 | tr '.:' ' ' )
  echo $(((h*60*60*1000)+(m*60*1000)+(s*1000)+ms))
}

start_ts=10:33:56.104
stop_ts=10:36:10.102

START=$(ts_get_msec $start_ts)
STOP=$(ts_get_msec $stop_ts)
DIFF=$((STOP-START))

min=$((DIFF/(60*1000)))
sec=$(((DIFF%(60*1000))/1000))
ms=$(((DIFF%(60*1000))%1000))

echo "${min}:${sec}.$ms"

1
মিলিসেকনগুলি হ্যান্ডেল করার কোনও উপায় আছে, উদাহরণস্বরূপ 10: 33: 56.104
উমেশ রাজভান্ডারী

মিলিসেকেন্ড হ্যান্ডলিং দুর্ব্যবহার করে যদি মিলিসেকেন্ড ক্ষেত্রটি একটি শূন্য দিয়ে শুরু হয়। উদাহরণস্বরূপ, এমএস = "033" "027" এর পেছনের অঙ্কগুলি দেবে কারণ এমএস ক্ষেত্রটি অষ্টাল হিসাবে ব্যাখ্যা করা হচ্ছে। "প্রতিধ্বনি" ... "+ এমএস))" "তে ..." + $ {এমএস ## + (0)))) পরিবর্তন করা যতক্ষণ না "শপ্ট-এস এক্সগ্লোব" এর উপরে কোথাও প্রদর্শিত হবে লিপি. একজনকে সম্ভবত এইচ, এম এবং এস থেকে শীর্ষস্থানীয় শূন্যগুলি ফেলা উচিত ...
এরিক টাওয়ার

3
echo $(((60*60*$((10#$h)))+(60*$((10#$m)))+$((10#$s))))আমি যেহেতু পেয়েছি আমার জন্য কাজ করেছেvalue too great for base (error token is "08")
নিকলাস

6

এখানে কিছু যাদু:

time1=14:30
time2=$( date +%H:%M ) # 16:00
diff=$(  echo "$time2 - $time1"  | sed 's%:%+(1/60)*%g' | bc -l )
echo $diff hours
# outputs 1.5 hours

sed:একটি সূত্রের সাথে 1/60 এ রূপান্তর করতে একটি প্রতিস্থাপন করে । তারপরে যে সময় গণনা করা হয়bc


5

তারিখ অনুসারে (জিএনইউ কোরিউটিলস) 7.4 আপনি এখন পাটিগণিত করতে -d ব্যবহার করতে পারেন:

$ date -d -30days
Sat Jun 28 13:36:35 UTC 2014

$ date -d tomorrow
Tue Jul 29 13:40:55 UTC 2014

আপনি যে ইউনিটগুলি ব্যবহার করতে পারবেন তা হ'ল দিন, বছর, মাস, ঘন্টা, মিনিট এবং সেকেন্ড:

$ date -d tomorrow+2days-10minutes
Thu Jul 31 13:33:02 UTC 2014

3

ঘন্টা / মিনিট / সেকেন্ড দেখাতে ড্যানিয়েল কামিল কোজারের উত্তর থেকে অনুসরণ করা:

echo "Duration: $(($DIFF / 3600 )) hours $((($DIFF % 3600) / 60)) minutes $(($DIFF % 60)) seconds"

সুতরাং সম্পূর্ণ স্ক্রিপ্টটি হ'ল:

date1=$(date +"%s")
date2=$(date +"%s")
diff=$(($date2-$date1))
echo "Duration: $(($DIFF / 3600 )) hours $((($DIFF % 3600) / 60)) minutes $(($DIFF % 60)) seconds"

3

অথবা কিছুটা গুটিয়ে রাখুন

alias timerstart='starttime=$(date +"%s")'
alias timerstop='echo seconds=$(($(date +"%s")-$starttime))'

তারপরে এটি কাজ করে।

timerstart; sleep 2; timerstop
seconds=2

3

এখানে date"পূর্বে" ব্যবহার করে কেবল কমান্ডের ক্ষমতাগুলি ব্যবহার করে এবং শেষের সময়টি সংরক্ষণ করার জন্য দ্বিতীয় ভেরিয়েবল ব্যবহার না করে একটি সমাধান এখানে দেওয়া হয়েছে :

#!/bin/bash

# save the current time
start_time=$( date +%s.%N )

# tested program
sleep 1

# the current time after the program has finished
# minus the time when we started, in seconds.nanoseconds
elapsed_time=$( date +%s.%N --date="$start_time seconds ago" )

echo elapsed_time: $elapsed_time

এটি দেয়:

$ ./time_elapsed.sh 
elapsed_time: 1.002257120

2
% start=$(date +%s)
% echo "Diff: $(date -d @$(($(date +%s)-$start)) +"%M minutes %S seconds")"
Diff: 00 minutes 11 seconds

6
এই উত্তরটি অন্যান্য উত্তরগুলি না করে এমনটি কী করে তা জেনে রাখা সহায়ক হবে।
লুই

এটি আপনাকে অনুমোদিত যে কোনও ফরমেটে সহজেই সময়কাল আউটপুট দেয় date
রায়ান সি। থম্পসন

2

date আপনাকে পার্থক্য দিতে পারে এবং এটি আপনার জন্য ফর্ম্যাট করতে পারে (ওএস এক্স বিকল্প দেখানো হয়েছে)

date -ujf%s $(($(date -jf%T "10:36:10" +%s) - $(date -jf%T "10:33:56" +%s))) +%T
# 00:02:14

date -ujf%s $(($(date -jf%T "10:36:10" +%s) - $(date -jf%T "10:33:56" +%s))) \
    +'%-Hh %-Mm %-Ss'
# 0h 2m 14s

কিছু স্ট্রিং প্রক্রিয়াজাতকরণ সেই খালি মানগুলি মুছে ফেলতে পারে

date -ujf%s $(($(date -jf%T "10:36:10" +%s) - $(date -jf%T "10:33:56" +%s))) \
    +'%-Hh %-Mm %-Ss' | sed "s/[[:<:]]0[hms] *//g"
# 2m 14s

আপনি যদি প্রথমবারটিকে প্রথমে রাখেন তবে এটি কাজ করবে না। যদি আপনার এটি পরিচালনা করতে হয় তবে এটিকে পরিবর্তন $(($(date ...) - $(date ...)))করুন$(echo $(date ...) - $(date ...) | bc | tr -d -)


1

mencoder( --endposএটি তুলনামূলক) এর সাথে ব্যবহারের জন্য আমার একটি সময় পার্থক্য স্ক্রিপ্টের প্রয়োজন ছিল এবং আমার সমাধানটি পাইথন স্ক্রিপ্ট কল করা:

$ ./timediff.py 1:10:15 2:12:44
1:02:29

সেকেন্ডের ভগ্নাংশও সমর্থিত:

$ echo "diff is `./timediff.py 10:51.6 12:44` (in hh:mm:ss format)"
diff is 0:01:52.4 (in hh:mm:ss format)

এবং এটি আপনাকে বলতে পারে যে 200 এবং 120 এর মধ্যে পার্থক্যটি 1h 20 মি:

$ ./timediff.py 120:0 200:0
1:20:0

এবং যে কোনও (সম্ভবত ভগ্নাংশ) সেকেন্ড বা মিনিট বা ঘন্টাকে এইচ: মিমি: এসএস এ রূপান্তর করতে পারে

$ ./timediff.py 0 3600
1:00:0
$ ./timediff.py 0 3.25:0:0
3:15:0

timediff.py:

#!/usr/bin/python

import sys

def x60(h,m):
    return 60*float(h)+float(m)

def seconds(time):
    try:
       h,m,s = time.split(':')
       return x60(x60(h,m),s)
    except ValueError:
       try:
          m,s = time.split(':')
          return x60(m,s)
       except ValueError:
          return float(time)

def difftime(start, end):
    d = seconds(end) - seconds(start)
    print '%d:%02d:%s' % (d/3600,d/60%60,('%02f' % (d%60)).rstrip('0').rstrip('.'))

if __name__ == "__main__":
   difftime(sys.argv[1],sys.argv[2])

1

জিএনইউ সহ units:

$ units
2411 units, 71 prefixes, 33 nonlinear units
You have: (10hr+36min+10s)-(10hr+33min+56s)
You want: s
    * 134
    / 0.0074626866
You have: (10hr+36min+10s)-(10hr+33min+56s)
You want: min
    * 2.2333333
    / 0.44776119

1

জিএনইউ তারিখ (বিশ্বস্ত উবুন্টু 14.04 এলটিএস) ব্যবহার করে @ নিসেতামার সমাধানটি সাধারণকরণ:

start=`date`
# <processing code>
stop=`date`
duration=`date -ud@$(($(date -ud"$stop" +%s)-$(date -ud"$start" +%s))) +%T`

echo $start
echo $stop
echo $duration

ফলনশীল:

Wed Feb 7 12:31:16 CST 2018
Wed Feb 7 12:32:25 CST 2018
00:01:09

1
#!/bin/bash

START_TIME=$(date +%s)

sleep 4

echo "Total time elapsed: $(date -ud "@$(($(date +%s) - $START_TIME))" +%T) (HH:MM:SS)"
$ ./total_time_elapsed.sh 
Total time elapsed: 00:00:04 (HH:MM:SS)

1

এই ফাংশনটি সংজ্ঞায়িত করুন (say / .bashrc এ বলুন):

time::clock() {
    [ -z "$ts" ]&&{ ts=`date +%s%N`;return;}||te=`date +%s%N`
    printf "%6.4f" $(echo $((te-ts))/1000000000 | bc -l)
    unset ts te
}

এখন আপনি আপনার স্ক্রিপ্টগুলির অংশগুলির সময় নির্ধারণ করতে পারেন:

$ cat script.sh
# ... code ...
time::clock
sleep 0.5
echo "Total time: ${time::clock}"
# ... more code ...

$ ./script.sh
Total time: 0.5060

মৃত্যুদন্ড কার্যকর করতে বাধা খুঁজে পেতে খুব দরকারী।


0

আমি বুঝতে পারি এটি একটি পুরানো পোস্ট, তবে লগ ফাইল থেকে তারিখ এবং সময় নেবে এবং ব-দ্বীপটি গণনা করবে এমন স্ক্রিপ্টে কাজ করার সময় আমি আজ এটি পেরেছি। নীচের স্ক্রিপ্টটি অবশ্যই ওভারকিল, এবং আমি আমার যুক্তি এবং গণিতগুলি পরীক্ষা করার পরামর্শ দিচ্ছি।

#!/bin/bash

dTime=""
tmp=""

#firstEntry="$(head -n 1 "$LOG" | sed 's/.*] \([0-9: -]\+\).*/\1/')"
firstEntry="2013-01-16 01:56:37"
#lastEntry="$(tac "$LOG" | head -n 1 | sed 's/.*] \([0-9: -]\+\).*/\1/')"
lastEntry="2014-09-17 18:24:02"

# I like to make the variables easier to parse
firstEntry="${firstEntry//-/ }"
lastEntry="${lastEntry//-/ }"
firstEntry="${firstEntry//:/ }"
lastEntry="${lastEntry//:/ }"

# remove the following lines in production
echo "$lastEntry"
echo "$firstEntry"

# compute days in last entry
for i in `seq 1 $(echo $lastEntry|awk '{print $2}')`; do {
  case "$i" in
   1|3|5|7|8|10|12 )
    dTime=$(($dTime+31))
    ;;
   4|6|9|11 )
    dTime=$(($dTime+30))
    ;;
   2 )
    dTime=$(($dTime+28))
    ;;
  esac
} done

# do leap year calculations for all years between first and last entry
for i in `seq $(echo $firstEntry|awk '{print $1}') $(echo $lastEntry|awk '{print $1}')`; do {
  if [ $(($i%4)) -eq 0 ] && [ $(($i%100)) -eq 0 ] && [ $(($i%400)) -eq 0 ]; then {
    if [ "$i" = "$(echo $firstEntry|awk '{print $1}')" ] && [ $(echo $firstEntry|awk '{print $2}') -lt 2 ]; then {
      dTime=$(($dTime+1))
    } elif [ $(echo $firstEntry|awk '{print $2}') -eq 2 ] && [ $(echo $firstEntry|awk '{print $3}') -lt 29 ]; then {
      dTime=$(($dTime+1))
    } fi
  } elif [ $(($i%4)) -eq 0 ] && [ $(($i%100)) -ne 0 ]; then {
    if [ "$i" = "$(echo $lastEntry|awk '{print $1}')" ] && [ $(echo $lastEntry|awk '{print $2}') -gt 2 ]; then {
      dTime=$(($dTime+1))
    } elif [ $(echo $lastEntry|awk '{print $2}') -eq 2 ] && [ $(echo $lastEntry|awk '{print $3}') -ne 29 ]; then {
      dTime=$(($dTime+1))
    } fi
  } fi
} done

# substract days in first entry
for i in `seq 1 $(echo $firstEntry|awk '{print $2}')`; do {
  case "$i" in
   1|3|5|7|8|10|12 )
    dTime=$(($dTime-31))
    ;;
   4|6|9|11 )
    dTime=$(($dTime-30))
    ;;
   2 )
    dTime=$(($dTime-28))
    ;;
  esac
} done

dTime=$(($dTime+$(echo $lastEntry|awk '{print $3}')-$(echo $firstEntry|awk '{print $3}')))

# The above gives number of days for sample. Now we need hours, minutes, and seconds
# As a bit of hackery I just put the stuff in the best order for use in a for loop
dTime="$(($(echo $lastEntry|awk '{print $6}')-$(echo $firstEntry|awk '{print $6}'))) $(($(echo $lastEntry|awk '{print $5}')-$(echo $firstEntry|awk '{print $5}'))) $(($(echo $lastEntry|awk '{print $4}')-$(echo $firstEntry|awk '{print $4}'))) $dTime"
tmp=1
for i in $dTime; do {
  if [ $i -lt 0 ]; then {
    case "$tmp" in
     1 )
      tmp="$(($(echo $dTime|awk '{print $1}')+60)) $(($(echo $dTime|awk '{print $2}')-1))"
      dTime="$tmp $(echo $dTime|awk '{print $3" "$4}')"
      tmp=1
      ;;
     2 )
      tmp="$(($(echo $dTime|awk '{print $2}')+60)) $(($(echo $dTime|awk '{print $3}')-1))"
      dTime="$(echo $dTime|awk '{print $1}') $tmp $(echo $dTime|awk '{print $4}')"
      tmp=2
      ;;
     3 )
      tmp="$(($(echo $dTime|awk '{print $3}')+24)) $(($(echo $dTime|awk '{print $4}')-1))"
      dTime="$(echo $dTime|awk '{print $1" "$2}') $tmp"
      tmp=3
      ;;
    esac
  } fi
  tmp=$(($tmp+1))
} done

echo "The sample time is $(echo $dTime|awk '{print $4}') days, $(echo $dTime|awk '{print $3}') hours, $(echo $dTime|awk '{print $2}') minutes, and $(echo $dTime|awk '{print $1}') seconds."

আপনি নিম্নলিখিত হিসাবে আউটপুট পাবেন।

2012 10 16 01 56 37
2014 09 17 18 24 02
The sample time is 700 days, 16 hours, 27 minutes, and 25 seconds.

আমি এটিকে এককভাবে তৈরি করতে স্ক্রিপ্টটি কিছুটা পরিবর্তন করেছি (উদাহরণস্বরূপ, কেবল পরিবর্তনশীল মানগুলি সেট করে), তবে সম্ভবত সাধারণ ধারণাটিও আসে comes নেতিবাচক মানগুলি পরীক্ষা করতে আপনি কিছু অতিরিক্ত ত্রুটি দেখতে চাইবেন।


জি, অনেক কাজ !! : দয়া করে আমার উত্তর তাকান stackoverflow.com/a/24996647/2350426

0

আমি ম্যাকালেয়ার জবাব সম্পর্কে মন্তব্য করতে পারি না, তাই এখানে এটি পোস্ট করছি। "ডিফ" পরিবর্তনশীল ছোট ক্ষেত্রে হওয়া উচিত। এখানে একটি উদাহরণ।

[root@test ~]# date1=$(date +"%s"); date
Wed Feb 21 23:00:20 MYT 2018
[root@test ~]# 
[root@test ~]# date2=$(date +"%s"); date
Wed Feb 21 23:00:33 MYT 2018
[root@test ~]# 
[root@test ~]# diff=$(($date2-$date1))
[root@test ~]# 

পূর্বের ভেরিয়েবলটি লোয়ার ক্ষেত্রে ঘোষণা করা হয়েছিল। যখন আপার কেস ব্যবহার করা হয় তখন এটি ঘটেছিল।

[root@test ~]# echo "Duration: $(($DIFF / 3600 )) hours $((($DIFF % 3600) / 60)) minutes $(($DIFF % 60)) seconds"
-bash: / 3600 : syntax error: operand expected (error token is "/ 3600 ")
[root@test ~]# 

সুতরাং, দ্রুত ফিক্স এই মত হবে

[root@test ~]# echo "Duration: $(($diff / 3600 )) hours $((($diff % 3600) / 60)) minutes $(($diff % 60)) seconds"
Duration: 0 hours 0 minutes 13 seconds
[root@test ~]# 

-1

এখানে আমার বাশ বাস্তবায়ন (অন্যান্য এসও ;-) থেকে নেওয়া বিট সহ)

function countTimeDiff() {
    timeA=$1 # 09:59:35
    timeB=$2 # 17:32:55

    # feeding variables by using read and splitting with IFS
    IFS=: read ah am as <<< "$timeA"
    IFS=: read bh bm bs <<< "$timeB"

    # Convert hours to minutes.
    # The 10# is there to avoid errors with leading zeros
    # by telling bash that we use base 10
    secondsA=$((10#$ah*60*60 + 10#$am*60 + 10#$as))
    secondsB=$((10#$bh*60*60 + 10#$bm*60 + 10#$bs))
    DIFF_SEC=$((secondsB - secondsA))
    echo "The difference is $DIFF_SEC seconds.";

    SEC=$(($DIFF_SEC%60))
    MIN=$((($DIFF_SEC-$SEC)%3600/60))
    HRS=$((($DIFF_SEC-$MIN*60)/3600))
    TIME_DIFF="$HRS:$MIN:$SEC";
    echo $TIME_DIFF;
}

$ countTimeDiff 2:15:55 2:55:16
The difference is 2361 seconds.
0:39:21

পরীক্ষিত নয়, বগিও হতে পারে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.