GNU/Linux >> Belajar Linux >  >> Linux

Bagaimana cara mengonversi dari hari ke tahun dan tahun ke tanggal YYYYMMDD?

Fungsi Bash ini berfungsi untuk saya di sistem berbasis GNU:

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

Beberapa contoh:

$ 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

Fungsi ini menganggap hari nol Julian sebagai hari terakhir tahun sebelumnya.

Dan inilah fungsi bash untuk sistem berbasis UNIX, seperti macOS:

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

Tidak dapat dilakukan hanya dalam Bash, tetapi jika Anda memiliki Perl:

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;

Jalankan info 'Date input formats' untuk melihat format apa yang diizinkan.

Format tanggal YYYY-DDD sepertinya tidak ada, dan mencoba

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

menunjukkan itu tidak berfungsi, jadi saya pikir njd benar, cara terbaik adalah menggunakan alat eksternal selain bash dan date .

Jika Anda benar-benar hanya ingin menggunakan bash dan alat baris perintah dasar, Anda dapat melakukan sesuatu seperti ini:

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
}

Tapi itu cara yang cukup lambat untuk melakukannya.

Cara yang lebih cepat namun lebih kompleks mencoba mengulang setiap bulan, menemukan hari terakhir di bulan tersebut, lalu melihat apakah hari Julian berada dalam rentang tersebut.

# 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
}

Linux
  1. Cara Meningkatkan ke Ubuntu 22.04 LTS dari Ubuntu 20.04 LTS dan 21.10

  2. Cara Melihat Tanggal dan Waktu Reboot Sistem Linux

  3. Bagaimana cara menggunakan sched_getaffinity dan sched_setaffinity di Linux dari C?

  1. Cara menyinkronkan tanggal dan waktu dari baris perintah di Ubuntu

  2. Bagaimana mengkonversi dari CentOS Linux 8 ke CentOS Stream 8

  3. Cara mengonversi file teks dari Shift JIS ke UTF-8 dan kembali dari terminal

  1. Cara Mendapatkan Tanggal dan Waktu Saat Ini dengan Python

  2. Cara menyetel tanggal dan waktu di AlmaLinux

  3. Bagaimana cara menambahkan X hari ke tanggal dan mendapatkan tanggal baru?