現在の日付から "xyz/[int][int]/[int][int][int][int]" 形式の日付を減算するには?

現在の日付から "xyz/[int][int]/[int][int][int][int]" 形式の日付を減算するには?

想像する

私のコンテナの最後の配布日は次の形式です。

月/日/年または2024年2月11日。

最終配布日の出力方法を変更することはできません。

現在の日付から最後の配布日を引いた後、最後の配布日が2ヶ月以上経過した場合は、ファイルに書きたいと思います。

たとえば、コンテナ1 - 最後 - deploy.txt:

last deployed: jan/01/2024

これらのファイルはいくつかあります。

問題は、月が文字で提供されることです。正規表現を使用して日付を取得できます。

私が考えた1つの解決策は、次のように月を事前に置くことです。

dict=(
  ['jan']=1
  ['feb']=2
)

しかし、もっと良い方法があるでしょう。

アルファベットの月を整数に変換できますか?

これはmacOSのbash用であり、bash 3ソリューションが望ましいです。

答え1

MacOS date- 日付文字列をエポックから秒に変換する

dateこのコマンドは、libc関数を介して文字列形式の月を理解できますstrptime(3)。私はmacosがないので答えをテストすることはできませんが、macosによるとdate 男性ページ:

date [-jRu] -f input_fmt new_date [+output_fmt]

[...]

   -f      Use input_fmt as the format string to parse the new_date provided rather than using the
           default [[[mm]dd]HH]MM[[cc]yy][.ss] format.  Parsing is done using strptime(3).

これで、マニュアルページで入力日をフォーマットする方法を知ることができます。strptime(3):

       %b or %B or %h
              The month name according to the current locale,  in  abbreviated
              form or the full name.

       %d or %e
              The day of month (1-31).

       %Y     The year, including century (for example, 1991).

したがって、これによれば、入力形式は次のようになります"%b/%e/%Y"

次に、次のフラグを使用する必要がありますdate

   -j      Do not try to set the date.  This allows you to use the -f flag in addition to the + option
           to convert one date format to another.  Note that any date or time components unspecified
           by the -f format string take their values from the current time.

最後に、結果から現在時刻を減算できるようにしたいので、+出力_fmtする:

       %s     The number of seconds since the Epoch, 1970-01-01 00:00:00
              +0000 (UTC).  Leap seconds are not counted unless leap
              second support is available.

したがって、日付形式をepochに変換する結果コマンドは次のようになります。

$ DATE="jan/01/2024"
$ date -jf "%b/%e/%Y" $DATE +%s
1704060000

繰り返しますが、Macosがないため、これを確認するためにテストすることはできません。また、小文字の月を許可するかどうかはわかりませんが、月を大文字に置き換える必要がある場合は、次のよう$DATEに置き換えることができます。${DATE^}

完全性のために、次のコマンドを使用して同じことを行う方法も示します。

GNU date- 日付文字列をエポックから秒に変換する

dateGNUバージョンはより多くの自由を提供するので、より簡単です。

それから男性ページ:

       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.

dateしたがって、マイコンピュータでテストした結果、コマンドが理解できるように入力からスラッシュを削除する必要があります。

$ DATE="jan/01/2024"
$ echo ${DATE//\// }
jan 01 2024
$ date --date "${DATE//\// }"  +%s
1704060000

現在の日付から減算

これで、元の日付の新起源時間を持つようになりました。ただ変数に保存するだけです。たとえば、MacOSでは次のようになります。

$ ORIG_DATE=$(date -jf "%b/%e/%Y" $DATE +%s)

エポック以降の現在の日付を秒単位で表示するには、次の手順を実行します。

$ date +%s
1704965965

違いを秒単位で計算する方法は簡単です。

$ echo $(( $(date +%s ) - $ORIG_DATE ))
905967

答え2

正確な要件を取得しようとする必要があります(おそらく要件がありますが、ここに記載されていない可能性があります)。

  • 一つは、月の略語であると仮定されるロケールです。たとえば、ドイツ語のロケールでは、月名は英語のみのアプリケーションで印刷された日付を解析するときに問題を引き起こす可能性があります(例:mayismaioctis in German okt)。

    使用されている月の名前が現在のロケールと一致する場合は、デプロイdate -d "$(echo jan/01/2024 | tr / ' ')"日を簡単に解析できます。

  • もう一つの質問は、日付の違いを計算する方法です。

    • 日数(約60日)を計算するには、+%sformatパラメーターを使用して配布日と現在の日付を秒に変換し、その数値を引いた後に結果が60 * 86400より大きいことを確認します。

    • もっと複雑なルール(例:月別の日付の比較)に従いたい場合は、まだbashで実行できますが、より難しくなります。

答え3

anydateとanyを使用すると、awk説明したように実行されます。

$ awk -v now="$(date +%m/%Y)" -v dif=2 -F'[ /]' '
    BEGIN {
        split(now,n)
        now = n[1] + (n[2] * 12)
    }
    {
        mth = ( index("janfebmaraprmayjunjulaugsepoctnovdec",$3) + 2 ) / 3
        cur = mth + ($5 * 12)
    }
    (now - cur) > dif
' file
last deployed: oct/01/2023

上記のコードはこの入力ファイルで実行されます。

$ cat file
last deployed: oct/01/2023
last deployed: nov/01/2023
last deployed: dec/01/2023
last deployed: jan/01/2024

入力の月名が、Janまたはのようにすべて小文字でない場合は、JANスクリプトからに$3変更するだけです。tolower($3)

答え4

使用幸せ(以前のPerl_6)

まず、日付を有効な日付に変換します。ISO 8601日付:

~$ raku -pe 'BEGIN my %months = [Z=>] <Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec>, 1..12;  \
             s{ ^ .+? <( ( <.alpha>**3 ) (\/)  (\d**1..2)  (\/) (\d**4) } = "$4-{sprintf q[%02d], %months{$0.tclc}}-$2".Date;'  file
last deployed: 2024-01-01

心配しないでください。いつでも再フォーマットできます。

~$ raku -pe 'BEGIN my %months = [Z=>] <Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec>, 1..12;  \
             s{ ^ .+? <( ( <.alpha>**3 ) (\/)  (\d**1..2)  (\/) (\d**4) } = "$4-{sprintf q[%02d], %months{$0.tclc}}-$2".Date.mm-dd-yyyy("/");'  file
last deployed: 01/01/2024

この楽要素は今楽だからな日付オブジェクトに対して数学的計算を実行できます。

~$ raku -pe 'BEGIN my %months = [Z=>] <Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec>, 1..12;  \
             s{ ^ .+? <( ( <.alpha>**3 ) (\/)  (\d**1..2)  (\/) (\d**4) } = Date.new(now) - "$4-{sprintf q[%02d], %months{$0.tclc}}-$2".Date ~ " days ago";'  file
last deployed: 46 days ago  

より多くのコード例については、以下のリンクを参照してください。

https://docs.raku.org/言語/temporal.html
https://github.com/Raku/examples/tree/master/categories/cookbook/03dates-and-times
https://raku.org

関連情報