বছরের বছর এবং বছর থেকে YYYYMMDD তারিখে কীভাবে রূপান্তর করবেন?


11

আমি বছরের দিন (1-366) এবং বছরের (উদাহরণস্বরূপ 2011) YYYYMMDD ফর্ম্যাটে কোনও তারিখে যেতে চাইছি?


1
দিন 0 কোন দিনের প্রতিনিধিত্ব করে? সাধারণত এটি 1-366।
মাইকেল

উত্তর:


17

এই বাশ ফাংশনটি জিএনইউ-ভিত্তিক সিস্টেমে আমার জন্য কাজ করে:

jul () { date -d "$1-01-01 +$2 days -1 day" "+%Y%m%d"; }

কিছু উদাহরণ:

$ y=2011; od=0; for d in {-4..4} 59 60 {364..366} 425 426; do (( d > od + 1)) && echo; printf "%3s " $d; jul $y $d; od=$d; done
 -4 20101227
 -3 20101228
 -2 20101229
 -1 20101230
  0 20101231
  1 20110101
  2 20110102
  3 20110103
  4 20110104

 59 20110228
 60 20110301

364 20111230
365 20111231
366 20120101

425 20120229
426 20120301

এই ফাংশন জুলিয়ান দিনটিকে শূন্যকে আগের বছরের শেষ দিন হিসাবে বিবেচনা করে।

এবং এখানে ইউএনআইএক্স-ভিত্তিক সিস্টেমগুলির জন্য একটি বাশ ফাংশন রয়েছে যেমন ম্যাকোএস:

jul () { (( $2 >=0 )) && local pre=+; date -v$pre$2d -v-1d -j -f "%Y-%m-%d" $1-01-01 +%Y%m%d; }

2
এটি একটি দুর্দান্ত সমাধান। শুধুমাত্র জিএনইউ তারিখ, তবে এত ছোট।
মাইকেল

আমি কখনই জানতাম না যে জিএনইউ তারিখটি নমনীয়। ফ্যান্টাস্টিক।
এনজেড

জিএনইউ তারিখটি ব্যবহার করে কী দুর্দান্ত সমাধান। আপনি যদি ইউনিক্স সিস্টেমে যেমন ম্যাকোস হিসাবে একই কাজ করতে চান তবে আপনি এটি ব্যবহার করতে পারেন:jul () { date -v+$2d -v-1d -j -f "%Y-%m-%d" $1-01-01 +%Y%m%d; }
ম্যাক্যান্টসিন

1
@ এমক্যান্টসিন: ম্যাকওএস সংস্করণের জন্য ধন্যবাদ!
পরবর্তী বিজ্ঞপ্তি না দেওয়া পর্যন্ত বিরতি দেওয়া হয়েছে।

1
@ এমক্যান্টসিন: আমি আপনার সংস্করণটি পরিবর্তন করেছি যাতে এটি নেতিবাচক অফসেটগুলির সাথে কাজ করে।
পরবর্তী বিজ্ঞপ্তি না দেওয়া পর্যন্ত বিরতি দেওয়া হয়েছে।

4

শুধু বাশে করা যাবে না, তবে পার্ল থাকলে:

use POSIX;

my ($jday, $year) = (100, 2011);

# Unix time in seconds since Jan 1st 1970
my $time = mktime(0,0,0, $jday, 0, $year-1900);

# same thing as a list that we can use for date/time formatting
my @tm = localtime $time;

my $yyyymmdd = strftime "%Y%m%d", @tm;

1
আমি সত্যই নিশ্চিত যে তাঁর কাজটি কেবল বাশে করা যেতে পারে, যদিও এটি মার্জিত নয় (টাইমস্ট্যাম্পটিকে এটি ফর্ম্যাটেটিংয়ের গণনা করা সবচেয়ে খারাপ ক্ষেত্রে)। তবে এটি পরীক্ষা করার জন্য আমি কোনও লিনাক্স মেশিনের সামনে নেই।
ববি

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

dateকমান্ড ব্যবহার করে করা যেতে পারে। আমার উত্তর দেখুন। তবে পার্ল উপায়টি অনেক সহজ এবং দ্রুত।
মাইকেল

2
@ ব্যান্ডি: অবধিdate -d
ব্যবহারকারী 1686

+1: এটি ব্যবহার করছিল - ধন্যবাদ, তবে উপরের তারিখ -d পদ্ধতিটি উপস্থিত হয়েছিল।
উম্বর ফেররুলে

4

চালান info 'Date input formats'তা দেখতে ফরম্যাটের অনুমতি দেওয়া হয়।

হল YYYY-DDD তারিখ বিন্যাস সেখানে হবে বলে মনে হচ্ছে না, এবং চেষ্টা

$ date -d '2011-011'
date: invalid date `2011-011'

শো এটা কাজ করে না, তাই আমি মনে করি njdসঠিক, সবচেয়ে ভালো উপায় একটি বহিস্থিত ছাড়া অন্য টুল ব্যবহার হয় bashএবং date

আপনি যদি সত্যিই কেবল বাশ এবং বেসিক কমান্ড লাইন সরঞ্জামগুলি ব্যবহার করতে চান তবে আপনি এরকম কিছু করতে পারেন:

julian_date_to_yyyymmdd()
{
    date=$1    # assume all dates are in YYYYMMM format
    year=${date%???}
    jday=${date#$year}
    for m in `seq 1 12`; do
        for d in `seq 1 31`; do
            yyyymmdd=$(printf "%d%02d%02d" $year $m $d)
            j=$(date +"%j" -d "$yyyymmdd" 2>/dev/null)
            if test "$jday" = "$j"; then
                echo "$yyyymmdd"
                return 0
            fi
        done
    done
    echo "Invalid date" >&2
    return 1
}

তবে এটি করার জন্য এটি বেশ ধীর।

একটি দ্রুত কিন্তু আরও জটিল উপায়ে প্রতি মাসে লুপ নেওয়ার চেষ্টা করে, সেই মাসে শেষ দিনটি খুঁজে পায়, তারপরে দেখুন জুলিয়ান দিনটি সেই পরিসরে রয়েছে কিনা।

# year_month_day_to_jday <year> <month> <day> => <jday>
# returns 0 if date is valid, non-zero otherwise
# year_month_day_to_jday 2011 2 1 => 32
# year_month_day_to_jday 2011 1 32 => error
year_month_day_to_jday()
{
    # XXX use local or typeset if your shell supports it
    _s=$(printf "%d%02d%02d" "$1" "$2" "$3")
    date +"%j" -d "$_s"
}

# last_day_of_month_jday <year> <month>
# last_day_of_month_jday 2011 2 => 59
last_day_of_month_jday()
{
    # XXX use local or typeset if you have it
    _year=$1
    _month=$2
    _day=31

    # GNU date exits with 0 if day is valid, non-0 if invalid
    # try counting down from 31 until we find the first valid date
    while test $_day -gt 0; do
        if _jday=$(year_month_day_to_jday $_year $_month $_day 2>/dev/null); then
            echo "$_jday"
            return 0
        fi
        _day=$((_day - 1))
    done
    echo "Invalid date" >&2
    return 1
}

# first_day_of_month_jday <year> <month>
# first_day_of_month_jday 2011 2 => 32
first_day_of_month_jday()
{
    # XXX use local or typeset if you have it
    _year=$1
    _month=$2
    _day=1

    if _jday=$(year_month_day_to_jday $_year $_month 1); then
        echo "$_jday"
        return 0
    else
        echo "Invalid date" >&2
        return 1
    fi
}

# julian_date_to_yyyymmdd <julian day> <4-digit year>
# e.g. julian_date_to_yyyymmdd 32 2011 => 20110201
julian_date_to_yyyymmdd()
{
    jday=$1
    year=$2

    for m in $(seq 1 12); do
        endjday=$(last_day_of_month_jday $year $m)
        if test $jday -le $endjday; then
            startjday=$(first_day_of_month_jday $year $m)
            d=$((jday - startjday + 1))
            printf "%d%02d%02d\n" $year $m $d
            return 0
        fi
    done
    echo "Invalid date" >&2
    return 1
}

last_day_of_month_jdayউদাহরণস্বরূপ date -d "$yyyymm01 -1 day"(কেবলমাত্র জিএনইউ তারিখ) বা ব্যবহার করে প্রয়োগ করা যেতে পারে $(($(date +"%s" -d "$yyyymm01") - 86400))
মাইকেল

ব্যাশ ভালো হ্রাস করতে পারেন: ((day--))। বাশ এর forমতো লুপ রয়েছে for ((m=1; m<=12; m++))(এর দরকার নেই seq)। এটি ধরে নেওয়া বেশ নিরাপদ যে আপনি যে শেলগুলি ব্যবহার করছেন সেগুলির মধ্যে অন্যান্য বৈশিষ্ট্য রয়েছে local
পরবর্তী বিজ্ঞপ্তি না দেওয়া পর্যন্ত বিরতি দেওয়া হয়েছে।

আইআইআরসি লোকালটি পসিক্স দ্বারা নির্দিষ্ট করা হয়নি, তবে একেবারে, যদি ksh ব্যবহার করে টাইপসেট থাকে, zsh স্থানীয় থাকে এবং zsh IIRC ঘোষণা করে। আমার মনে হয় টাইপসেটটি 3 টিতে কাজ করে তবে ছাই / ড্যাশে কাজ করে না। আমি ksh- স্টাইলের জন্য কম ব্যবহার করি না। চিন্তাভাবনার জন্য ধন্যবাদ।
মাইকেল


হ্যাঁ, তবে আইআইআরসি টাইপসেট নয়। অন্য সকলের টাইপসেট রয়েছে। যদি ড্যাশটিরও টাইপসেট থাকে তবে আমি উদাহরণটিতে এটি ব্যবহার করতাম।
মাইকেল

1

যদি বছরের দিন (1-366) হয় 149 এবং বছর হয় 2014 ,

$ date -d "148 days 2014-01-01" +"%Y%m%d"
20140529

বছরের -1 মানের দিনটি ইনপুট করতে ভুলবেন না ।


0

ব্যাশ আমার সমাধান

from_year=2013
from_day=362

to_year=2014
to_day=5

now=`date +"%Y/%m/%d" -d "$from_year/01/01 + $from_day days - 2 day"`
end=`date +"%Y/%m/%d" -d "$to_year/01/01 + $to_day days - 1 day"`


while [ "$now" != "$end" ] ; 
do
    now=`date +"%Y/%m/%d" -d "$now + 1 day"`;
    echo "$now";
    calc_day=`date -d "$now" +%G'.'%j`
    echo $calc_day
done

0

পসিক্স টার্মিনালে:

jul () { date -v$1y -v1m -v1d -v+$2d -v-1d "+%Y%m%d"; }

তারপরে কল করুন

jul 2011 012
jul 2017 216
jul 2100 60

0

আমি বুঝতে পারি যে এটি বহু বছর আগে জিজ্ঞাসা করা হয়েছিল, তবে আমি যে উত্তরগুলি দেখছি তার মধ্যে কোনওটিই খাঁটি BASH হিসাবে বিবেচনা করে না কেন তারা সবাই জিএনইউ ব্যবহার করে date। আমি ভেবেছিলাম আমি উত্তর দেওয়ার সময় ছুরিকাঘাত করব ... তবে আমি আপনাকে আগেই সতর্ক করে দিয়েছিলাম, উত্তরটি মার্জিত নয়, বা এটি 100 টিরও বেশি লাইনে সংক্ষিপ্ত নয়। এটি নিখুঁত করা যেতে পারে, তবে আমি অন্যদের সহজেই এটি কী করে তা দেখতে দিতে চাই।

এখানে প্রাথমিক "কৌশলগুলি" এক বছরের লিপ ইয়ার (বা না) %বছরের মোডুলাসকে 4 দ্বারা বিভক্ত করে, এবং তারপরে প্রতিটি মাসের দিনগুলি যোগ করে, প্রয়োজনে ফেব্রুয়ারির জন্য একটি অতিরিক্ত দিন নির্ধারণ করছে , মানগুলির একটি সাধারণ টেবিল ব্যবহার করে।

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

কোডটিতে ... আমি আশা করি এটি বেশ স্ব-বর্ণনামূলক।

#!/bin/sh

# Given a julian day of the year and a year as ddd yyyy, return
# the values converted to yyyymmdd format using ONLY bash:

ddd=$1
yyyy=$2
if [ "$ddd" = "" ] || [ "$yyyy" = "" ]
then
  echo ""
  echo "   Usage: <command> 123 2016"
  echo ""
  echo " A valid julian day from 1 to 366 is required as the FIRST"
  echo " parameter after the command, and a valid 4-digit year from"
  echo " 1901 to 2099 is required as the SECOND. The command and each"
  echo " of the parameters must be separated from each other with a space."
  echo " Please try again."
  exit
fi
leap_yr=$(( yyyy % 4 ))
if [ $leap_yr -ne 0 ]
then
  leap_yr=0
else
  leap_yr=1
fi
last_doy=$(( leap_yr + 365 ))
while [ "$valid" != "TRUE" ]
do
  if [ 0 -lt "$ddd" ] && [ "$last_doy" -ge "$ddd" ]
  then
    valid="TRUE"
  else
    echo "   $ddd is an invalid julian day for the year given."
    echo "   Please try again with a number from 1 to $last_doy."
    exit    
  fi
done
valid=
while [ "$valid" != "TRUE" ]
do
  if [ 1901 -le "$yyyy" ] && [ 2099 -ge "$yyyy" ]
  then
    valid="TRUE"
  else
    echo "   $yyyy is an invalid year for this script."
    echo "   Please try again with a number from 1901 to 2099."
    exit    
  fi
done
if [ "$leap_yr" -eq 1 ]
then
  jan=31  feb=60  mar=91  apr=121 may=152 jun=182
  jul=213 aug=244 sep=274 oct=305 nov=335
else
  jan=31  feb=59  mar=90  apr=120 may=151 jun=181
  jul=212 aug=243 sep=273 oct=304 nov=334
fi
if [ "$ddd" -gt $nov ]
then
  mm="12"
  dd=$(( ddd - nov ))
elif [ "$ddd" -gt $oct ]
then
  mm="11"
  dd=$(( ddd - oct ))
elif [ "$ddd" -gt $sep ]
then
  mm="10"
  dd=$(( ddd - sep ))
elif [ "$ddd" -gt $aug ]
then
  mm="09"
  dd=$(( ddd - aug ))
elif [ "$ddd" -gt $jul ]
then
  mm="08"
  dd=$(( ddd - jul ))
elif [ "$ddd" -gt $jun ]
then
  mm="07"
  dd=$(( ddd - jun ))
elif [ "$ddd" -gt $may ]
then
  mm="06"
  dd=$(( ddd - may ))
elif [ "$ddd" -gt $apr ]
then
  mm="05"
  dd=$(( ddd - apr ))
elif [ "$ddd" -gt $mar ]
then
  mm="04"
  dd=$(( ddd - mar ))
elif [ "$ddd" -gt $feb ]
then
  mm="03"
  dd=$(( ddd - feb ))
elif [ "$ddd" -gt $jan ]
then
  mm="02"
  dd=$(( ddd - jan ))
else
  mm="01"
  dd="$ddd"
fi
if [ ${#dd} -eq 1 ]
then
  dd="0$dd"
fi
if [ ${#yyyy} -lt 4 ]
then
  until [ ${#yyyy} -eq 4 ]
  do
    yyyy="0$yyyy"
  done
fi
printf '\n   %s%s%s\n\n' "$yyyy" "$mm" "$dd"

তবে, প্রকৃত লিপ ইয়ার গণনা "4 দ্বারা বিভাজ্য" এর চেয়ে কিছুটা জটিল।
এরিখ

@ অরিচ - আপনি সঠিক, তবে এই স্ক্রিপ্ট (1901-2099) দ্বারা বৈধ হিসাবে অনুমোদিত কয়েক বছরের মধ্যে, কাজ করবে না এমন পরিস্থিতি ঘটবে না। বছরগুলিতে ডিল করার জন্য একটি "বা" পরীক্ষা যুক্ত করা খুব কঠিন নয় যে ব্যবহারকারীর যদি এটির প্রসারিত করার প্রয়োজন হয় তবে এই ক্ষেত্রেগুলি কভার করার জন্য 400 দ্বারা সমানভাবে বিভাজ্য নয়, তবে আমি অনুভব করি নি যে আসলেই এটির দরকার ছিল এই ক্ষেত্রে. সম্ভবত এটি আমার পক্ষে স্বল্পদৃষ্টির ছিল?
ডেভ লিডিক

0
OLD_JULIAN_VAR=$(date -u -d 1840-12-31 +%s)

TODAY_DATE=`date --date="$odate" +"%Y-%m-%d"`
TODAY_DATE_VAR=`date -u -d "$TODAY_DATE" +"%s"`
export JULIAN_DATE=$((((TODAY_DATE_VAR - OLD_JULIAN_VAR))/86400))
echo $JULIAN_DATE

গাণিতিকভাবে নীচে উপস্থাপন

[(date in sec)-(1840-12-31 in sec)]/(sec in a day 86400)
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.