কীভাবে ISO8601 তারিখগুলি লিনাক্স তারিখ কমান্ড দিয়ে পার্স করবেন


15

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

sh-4.2$ date
Fri Jan  3 14:22:19 PST 2014
sh-4.2$ date +%Y%m%dT%H%M
20140103T1422
sh-4.2$ date -d "20140103T1422"
Thu Jan  2 23:22:00 PST 2014

তারিখটি 15 ঘন্টার অফসেট দিয়ে স্ট্রিংটির ব্যাখ্যা দিচ্ছে বলে মনে হয়। এটির জন্য কি কোনও পরিচিত ওয়ার্কআরউন্ডস রয়েছে?

সম্পাদনা করুন: এটি কোনও প্রদর্শনের বিষয় নয়:

sh-4.2$ date +%s
1388791096
sh-4.2$ date +%Y%m%dT%H%M
20140103T1518
sh-4.2$ date -d 20140103T1518 +%s
1388737080
sh-4.2$ python
Python 3.3.3 (default, Nov 26 2013, 13:33:18) 
[GCC 4.8.2] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> 1388737080 - 1388791096
-54016
>>> 54016/3600
15.004444444444445
>>> 

এটি এখনও ইউনিক্স টাইমস্ট্যাম্প হিসাবে প্রদর্শিত হবে 15 ঘন্টা দ্বারা বন্ধ।

সম্পাদনা # 1

আমার এই প্রশ্নটি কিছুটা ভিন্নভাবে প্রকাশ করা উচিত। বলুন আমার কাছে ফর্মের ISO8601 বেসিক টাইমস্ট্যাম্পগুলির একটি তালিকা রয়েছে:

  • YYYYMMDDThhmm
  • YYYYMMDDThhmmss

এগুলি সম্পর্কিত ইউনিক্স টাইমস্ট্যাম্পগুলিতে রূপান্তর করার সহজ উপায় কী?

উদাহরণ স্বরূপ:

- 20140103T1422   = 1388787720
- 20140103T142233 = 1388787753

1
@ ড্র্রুবেন আমার টাইমস্ট্যাম্পে কোনও বিশেষ চরিত্র থাকতে পারে না। শুধু সংখ্যা এবং চিঠি। সুতরাং না, আমি এটি করতে পারি না, দুর্ভাগ্যক্রমে।
অ্যালেক্স.ফরঞ্চিচ

@ সিম টিজেড সেট করা নেই, তবে / ইত্যাদি / স্থানীয় সময় সংযুক্ত রয়েছে।
অ্যালেক্স.ফরঞ্চিচ

আপনি আমাকে হত্যা করছেন, এটি কি আপনার চূড়ান্ত প্রশ্ন? 8-)
slm

20140103T1518বৈধ আইএসও 8601 নয়, এটি টাইমজোন অংশটি মিস করেছে
ফেরিবিগ

উত্তর:


9

আপনি "পরিচিত কাজের সীমা" চেয়েছেন ask এখানে একটি সহজ:

$ date -d "$(echo 20140103T1422 | sed 's/T/ /')"
Fri Jan  3 14:22:00 PST 2014

এটি sedএকটি স্থান দিয়ে "টি" প্রতিস্থাপন করতে ব্যবহার করে। ফলাফলটি এমন ফর্ম্যাট যা dateবোঝে।

যদি আমরা আইএসও 8601 তারিখে সেকেন্ড যোগ করি, তবে dateআরও পরিবর্তন প্রয়োজন:

$ date -d "$(echo 20140103T142211 | sed -r 's/(.*)T(..)(..)(..)/\1 \2:\3:\4/')"
Fri Jan  3 14:22:11 PST 2014

উপরের sedঅংশে, "টি" কে একটি স্থানের সাথে প্রতিস্থাপন করে এবং এইচএইচএমএমএসএসকেও এইচএইচএমএম: এসএসে পৃথক করে।


+ মুছে ফেলা হলে আমার পক্ষে কাজ করে। তবে এটি দ্বিতীয় সুনির্দিষ্ট টাইমস্ট্যাম্পগুলির জন্য কাজ করে না, কেবলমাত্র মিনিটের যথার্থতা।
অ্যালেক্স.ফরঞ্চিচ

@ অ্যালেক্স.ফরঞ্চিচ উত্তর সেকেন্ডের নির্ভুলতার সাথে আপডেট হয়েছে। আমি যে সেকেন্ডের ফর্ম্যাটটি বেছে নিয়েছি তা যদি আপনার প্রয়োজন হয় না তবে আমাকে জানান।
1024

8

Coreutils তথ্য ডক্স যে আইএসও 8601 "প্রসারিত বিন্যাস" সমর্থিত বলেছেন।

+%zএটিকে কাজ করতে আপনাকে হাইফেন, কলোন এবং একটি যুক্ত করতে হবে।

$ date +"%Y-%m-%dT%H:%M:%S%z"
2014-01-03T16:08:23-0800
$ date -d 2014-01-03T16:08:23-0800
Fri Jan  3 16:08:23 PST 2014

আপনার প্রশ্নের দ্বিতীয় অংশের উত্তর দিতে ...

যেহেতু তারিখের ফর্ম্যাটটিতে কেবল সংখ্যা এবং চিহ্ন রয়েছে, আপনি প্রতিটি চিহ্নকে একটি অনন্য বর্ণের সাথে প্রতিস্থাপন করতে পারেন, উদাহরণস্বরূপ using tr

$ ts="$(date +"%Y-%m-%dT%H:%M:%S%z" | tr -- '-:+' 'hcp')"; echo "$ts"
2014h01h03T16c18c04h0800
$ date -d "$(echo "$ts" | tr -- 'hcp' '-:+')"
Fri Jan  3 16:18:04 PST 2014

অথবা আপনি কি ব্যবহার করে এটিকে পার্স পারে Tএবং -বা +বিভাজক, যেমন যেমন শেল ব্যবহার ${var%word}এবং ${var#word}বিস্তার

$ ts="$(date +"%Y%m%dT%H%M%S%z")"; echo "$ts"
20140103T162228-0800
$ date=${ts%T*}; time=${ts#*T}
etc.    

বা bashনিয়মিত এক্সপ্রেশন ম্যাচ ব্যবহার করে

$ ts="$(date +"%Y%m%dT%H%M%S%z")"; echo "$ts"
20140103T165611-0800
$ [[ "$ts" =~ (.*)(..)(..)T(..)(..)(..)(.....) ]]
$ match=("${BASH_REMATCH[@]}")
$ Y=${match[1]}; m=${match[2]}; d=${match[3]}; H=${match[4]}; M=${match[5]}; S=${match[6]}; z=${match[7]}
$ date -d "$Y-$m-$d"T"$H:$M:$S$z"
Fri Jan  3 16:56:11 PST 2014

বা পার্ল, পাইথন ইত্যাদি


টাইমস্ট্যাম্পের এতে কোনও বিশেষ অক্ষর থাকতে পারে না। এগুলি আবার স্বয়ংক্রিয়ভাবে যুক্ত করার কোনও ভাল উপায় সম্পর্কে আপনি কি জানেন?
অ্যালেক্স.ফরঞ্চিচ

6

জিএনইউ কোর্টিলগুলি সংস্করণ 8.13 থেকে ইনপুট হিসাবে কেবল আইএসও 8601 তারিখকে সমর্থন করেছে (2011-09-08 এ প্রকাশিত) । আপনার অবশ্যই একটি পুরানো সংস্করণ ব্যবহার করা উচিত।

পুরানো সংস্করণগুলির অধীনে, আপনাকে Tএকটি স্থান দ্বারা প্রতিস্থাপন করতে হবে । অন্যথায় এটি মার্কিন সামরিক সময় অঞ্চল হিসাবে ব্যাখ্যা করা হয় ।

এমনকি সাম্প্রতিক সংস্করণগুলির অধীনে, কেবলমাত্র সম্পূর্ণ বিরামচিহ্নযুক্ত ফর্মটি স্বীকৃত, কেবলমাত্র অঙ্ক এবং Tমাঝখানে একটি সহ প্রাথমিক বিন্যাসটি নয় ।

# Given a possibly abbreviated ISO date $iso_date...
date_part=${iso_date%%T*}
if [ "$date_part" != "$iso_date" ]; then
  time_part=${abbreviated_iso_date#*T}
  case ${iso_date#*T} in
    [!0-9]*) :;;
    [0-9]|[0-9][0-9]) time_part=${time_part}:00;;
    *)
      hour=${time_part%${time_part#??}}
      minute=${time_part%${time_part#????}}; minute=${minute#??}
      time_part=${hour}:${minute}:${time_part#????};;
  esac
else
  time_part=
fi
date -d "$date_part $time_part"

2

আমি ম্যান পেজে এই নোটটি লক্ষ্য করেছি date

DATE STRING
      The --date=STRING is a mostly free format human readable date string
      such as "Sun, 29 Feb 2004 16:21:42 -0800"  or  "2004-02-29
      16:21:42"  or  even  "next Thursday".  A date string may contain 
      items indicating calendar date, time of day, time zone, day of
      week, relative time, relative date, and numbers.  An empty string 
      indicates the beginning of the day.  The date  string  format
      is more complex than is easily documented here but is fully described 
      in the info documentation.

এটি চূড়ান্ত নয় তবে এটি T[আইএসও 8601] এর জন্য স্পষ্টভাবে একটি সময় বিন্যাসের স্ট্রিং দেখায় না যা এতে আপনি চেষ্টা করছেন includes @ গিলিস উত্তর হিসাবে ইঙ্গিত , GNU CoreUtils এ আইএসও 8601 এর সমর্থন তুলনামূলকভাবে নতুন।

স্ট্রিংটির পুনরায় ফর্ম্যাট করা

আপনি আপনার স্ট্রিং সংস্কার করতে পার্ল ব্যবহার করতে পারেন।

উদাহরণ:

$ date -d "$(perl -pe 's/(.*)T(\d{2})(\d{2})(\d{2})/$1 $2:$3:$4/' \
    <<<"20140103T142233")"
Fri Jan  3 14:22:33 EST 2014

আপনি এই হ্যান্ডেলটিকে উভয় স্ট্রিং তৈরি করতে পারেন যার মধ্যে সেকেন্ড এবং যেটি নেই include

20140103T1422:

$ date -d "$(perl -pe 's/^(.*)T(\d{2})(\d{2})(\d{2})$/$1 $2:$3:$4/ || \
     s/^(.*)T(\d{2})(\d{2})$/$1 $2:$3:00/' <<<"20140103T1422")"
Fri Jan  3 14:22:00 EST 2014

20140103T142233:

$ date -d "$(perl -pe 's/^(.*)T(\d{2})(\d{2})(\d{2})$/$1 $2:$3:$4/ || \
     s/^(.*)T(\d{2})(\d{2})$/$1 $2:$3:00/' <<<"20140103T142233")"
Fri Jan  3 14:22:33 EST 2014

@ অ্যালেক্স.ফরনসিচ - একটি বিকল্প কমান্ড যা উভয় সময় বিন্যাস পরিচালনা করবে। আমার পক্ষে কোন পক্ষ করুন এবং উপরের মন্তব্যগুলি মুছুন যা এখন আর প্রাসঙ্গিক নয়।
slm

1

তারিখের ম্যান পেজ অনুসারে, আপনার যে ফর্ম্যাটটি আউটপুট আউটপুট হিসাবে dateপ্রত্যাশিত হয় তা একই নয় । ম্যান পেজ এটাই বলে:

date [-u|--utc|--universal] [MMDDhhmm[[CC]YY][.ss]]

সুতরাং আপনি এটি এইভাবে করতে পারে:

# date +%m%d%H%M%Y
010402052014
# date 010402052014
Sat Jan  4 02:05:00 EAT 2014

কারণ আউটপুট স্ট্রিং সংজ্ঞায়িত করতে যে ভেরিয়েবলগুলি ব্যবহৃত হয়, +%m%d%H%M%Yএটি ইনপুট হিসাবে প্রত্যাশার সমান হবে।


তারপরে আপনি কোনও ISO8601 ফর্ম্যাট তারিখটি কোন তারিখের জন্য ম্যাপ করতে একটি আদেশ সরবরাহ করতে পারেন? প্রকৃত সঞ্চিত টাইমস্ট্যাম্পগুলি ISO8601 ফর্ম্যাটে থাকতে হবে যাতে সেগুলি তারিখ অনুসারে বাছাই করা যায়।
অ্যালেক্স.ফরঞ্চিচ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.