GNU/Linux >> Znalost Linux >  >> Linux

Jak převést ze dne v roce a roku na datum RRRRMMDD?

Tato funkce Bash mi funguje na systému založeném na GNU:

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

Několik příkladů:

$ 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

Tato funkce považuje juliánský den nula za poslední den předchozího roku.

A zde je funkce bash pro systémy založené na UNIX, jako je macOS:

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

Nelze provést pouze v Bash, ale pokud máte 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;

Spusťte info 'Date input formats' abyste viděli, jaké formáty jsou povoleny.

Zdá se, že formát data RRRR-DDD zde není a pokouším se

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

ukazuje, že to nefunguje, takže si myslím, že njd je správné, nejlepším způsobem je použít externí nástroj jiný než bash a date .

Pokud opravdu chcete používat pouze bash a základní nástroje příkazového řádku, můžete udělat něco takového:

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
}

Ale to je docela pomalý způsob, jak to udělat.

Rychlejší, ale složitější způsob se pokouší procházet každý měsíc, najde poslední den v daném měsíci a poté zjistí, zda je juliánský den v tomto rozsahu.

# 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. Jak zobrazit datum a čas restartu systému Linux

  2. Jak používat sched_getaffinity a sched_setaffinity v Linuxu z C?

  3. Jak převést textový soubor z Shift JIS na UTF-8 a zpět z terminálu

  1. Jak synchronizovat datum a čas z příkazového řádku v Ubuntu

  2. Jak upgradovat na Ubuntu 22.04 LTS z Ubuntu 20.04 LTS a 21.10

  3. Jak přidám X dní k datu a získám nové datum?

  1. Jak získat aktuální datum a čas v Pythonu

  2. Jak nastavit datum a čas na AlmaLinuxu

  3. Jak převést z CentOS Linux 8 na CentOS Stream 8