지금까지 주어진 날짜까지 며칠을 반환하는 스크립트 또는 함수 며칠을 알려주는 스크립트 나 함수를 작성하고 싶습니다.

지금부터 앞으로 주어진 날짜까지 며칠을 알려주는 스크립트 나 함수를 작성하고 싶습니다. 내가 해결하기 위해 고군분투하는 것은 주어진 날짜를 처리하고 현재 날짜와 비교하는 방법입니다 … 나는 뭔가를 상상하고 있습니다.

read -p "enter the date in the format YYYY-MM-DD "

그리고 쉘에 무의미한 문자열이 있다고 가정하고 다음과 같은 몇 가지 평가를 수행해야합니다 … ?? (이것은 단지 예일뿐입니다. bc)

i=$(($(date +%Y)-${REPLY%%-*}))
j=$(($(date +%m)-${REPLY:5:2}))
k=$(($(date +%d)-${REPLY##*-}))

그리고 나는 그 숫자로 무엇을 해야할지 모르겠다.

if $i > 1 then assign l=$((i*365)) and else what?? # what about leap years?
Using $j somehow assign m   # confused before I've started
Using $k somehow assign n   # just as bad
echo $((l+m+n))   

나는 그것을 너무 힘들게 만들고있다. 아마도 날짜를 이해하고 비교할 수있는 텍스트 처리 도구가있을 것입니다.

어떻게해야합니까?



답변

에포크 시간

일반적으로 시간을 (Unix) 에포크 시간 (1-1-1970에서 초 )으로 변환하면 시간 계산이 가장 쉽습니다 . 파이썬에는 시간을 에포크 시간으로 변환하고 원하는 날짜 형식으로 되돌릴 수있는 도구가 있습니다.

다음과 같은 형식을 간단히 설정할 수 있습니다.

pattern = "%Y-%m-%d"

… 오늘 정의하십시오.

today = "2016-12-07"

그런 다음 작업을 수행하는 함수를 작성하십시오.

def convert_toepoch(pattern, stamp):
    return int(time.mktime(time.strptime(stamp, pattern)))

그런 다음 출력 :

nowepoch = convert_toepoch(pattern, today)
print(nowepoch)

> 1481065200

… 이것은 1-1-1970 이후의 초 수입니다.

두 날짜 사이의 날짜 계산

오늘과 미래의 날짜 에이 작업을 수행하면 차액을 계산하십시오.

#!/usr/bin/env python3
import time

# set our date pattern
pattern = "%Y-%m-%d"

def convert_toepoch(pattern, stamp):
    return int(time.mktime(time.strptime(stamp, pattern)))

# automatically get today's date 
today = time.strftime(pattern); future = "2016-12-28"

nowepoch = convert_toepoch(pattern, today)
future_epoch = convert_toepoch(pattern, future)

print(int((future_epoch - nowepoch)/86400))

출력은 형식을 사용하므로 날짜 별로 계산됩니다 %Y-%m-%d. 예를 들어 24 시간이 지나면 초를 반올림 하면 날짜 차이가 잘못 될 수 있습니다.

터미널 버전

#!/usr/bin/env python3
import time

# set our date pattern
pattern = "%Y-%m-%d"

def convert_toepoch(pattern, stamp):
    return int(time.mktime(time.strptime(stamp, pattern)))

# automatically get today's date 
today = time.strftime(pattern)
# set future date
future = input("Please enter the future date (yyyy-mm-dd): ")
nowepoch = convert_toepoch(pattern, today)
future_epoch = convert_toepoch(pattern, future)
print(int((future_epoch - nowepoch)/86400))

여기에 이미지 설명을 입력하십시오

… 그리고 Zenity 옵션

#!/usr/bin/env python3
import time
import subprocess

# set our date pattern
pattern = "%Y-%m-%d"

def convert_toepoch(pattern, stamp):
    return int(time.mktime(time.strptime(stamp, pattern)))

# automatically get today's date 
today = time.strftime(pattern)
# set future date
try:
    future = subprocess.check_output(
        ["zenity", "--entry", "--text=Enter a date (yyyy-mm-dd)"]
        ).decode("utf-8").strip()
except subprocess.CalledProcessError:
    pass
else:
    nowepoch = convert_toepoch(pattern, today)
    future_epoch = convert_toepoch(pattern, future)
    subprocess.call(
        ["zenity", "--info",
         "--text="+str(int((future_epoch - nowepoch)/86400))
         ])

여기에 이미지 설명을 입력하십시오

여기에 이미지 설명을 입력하십시오

그리고 그냥 재미를 위해 …

작은 응용 프로그램. 자주 사용하는 경우 바로 가기에 추가하십시오.

여기에 이미지 설명을 입력하십시오

스크립트 :

#!/usr/bin/env python3
import time
import subprocess
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Pango, Gdk

class OrangDays(Gtk.Window):

    def __init__(self):

        self.pattern = "%Y-%m-%d"
        self.currdate = time.strftime(self.pattern)
        big_font = "Ubuntu bold 45"
        self.firstchar = True

        Gtk.Window.__init__(self, title="OrangeDays")
        maingrid = Gtk.Grid()
        maingrid.set_border_width(10)
        self.add(maingrid)

        datelabel = Gtk.Label("Enter date")
        maingrid.attach(datelabel, 0, 0, 1, 1)

        self.datentry = Gtk.Entry()
        self.datentry.set_max_width_chars(12)
        self.datentry.set_width_chars(12)
        self.datentry.set_placeholder_text("yyyy-mm-dd")
        maingrid.attach(self.datentry, 2, 0, 1, 1)

        sep1 = Gtk.Grid()
        sep1.set_border_width(10)
        maingrid.attach(sep1, 0, 1, 3, 1)

        buttongrid = Gtk.Grid()
        buttongrid.set_column_homogeneous(True)
        maingrid.attach(buttongrid, 0, 2, 3, 1)

        fakebutton = Gtk.Grid()
        buttongrid.attach(fakebutton, 0, 0, 1, 1)

        calcbutton = Gtk.Button("Calculate")
        calcbutton.connect("clicked", self.showtime)
        calcbutton.set_size_request(80,10)
        buttongrid.attach(calcbutton, 1, 0, 1, 1)

        fakebutton2 = Gtk.Grid()
        buttongrid.attach(fakebutton2, 2, 0, 1, 1)

        sep2 = Gtk.Grid()
        sep2.set_border_width(5)
        buttongrid.attach(sep2, 0, 1, 1, 1)

        self.span = Gtk.Label("0")
        self.span.modify_font(Pango.FontDescription(big_font))
        self.span.set_alignment(xalign=0.5, yalign=0.5)
        self.span.modify_fg(Gtk.StateFlags.NORMAL, Gdk.color_parse("#FF7F2A"))
        maingrid.attach(self.span, 0, 4, 100, 1)

        sep3 = Gtk.Grid()
        sep3.set_border_width(5)
        maingrid.attach(sep3, 0, 5, 1, 1)

        buttonbox = Gtk.Box()
        maingrid.attach(buttonbox, 0, 6, 3, 1)
        quitbutton = Gtk.Button("Quit")
        quitbutton.connect("clicked", Gtk.main_quit)
        quitbutton.set_size_request(80,10)
        buttonbox.pack_end(quitbutton, False, False, 0)

    def convert_toepoch(self, pattern, stamp):
        return int(time.mktime(time.strptime(stamp, self.pattern)))

    def showtime(self, button):
        otherday = self.datentry.get_text()
        try:
            nextepoch = self.convert_toepoch(self.pattern, otherday)
        except ValueError:
            self.span.set_text("?")
        else:
            todayepoch = self.convert_toepoch(self.pattern, self.currdate)
            days = str(int(round((nextepoch-todayepoch)/86400)))
            self.span.set_text(days)


def run_gui():
    window = OrangDays()
    window.connect("delete-event", Gtk.main_quit)
    window.set_resizable(True)
    window.show_all()
    Gtk.main()

run_gui()
  • 빈 파일로 복사하여 다른 이름으로 저장하십시오. orangedays.py
  • 그것을 실행 :

    python3 /path/to/orangedays.py

마무리

다음 .desktop파일 위의 작은 응용 프로그램 스크립트에 사용하십시오 .

[Desktop Entry]
Exec=/path/to/orangedays.py
Type=Application
Name=Orange Days
Icon=org.gnome.Calendar

여기에 이미지 설명을 입력하십시오

  • 빈 파일에 코드를 복사하여 다음과 같이 저장하십시오 orangedays.desktop.~/.local/share/applications
  • 라인에서

    Exec=/path/to/orangedays.py

    스크립트의 실제 경로를 설정하십시오 …


답변

GNU의 date유틸리티는 이런 종류의 꽤 좋다. 다양한 날짜 형식을 구문 분석 한 다음 다른 형식으로 출력 할 수 있습니다. 여기서 우리 %s는 에포크 이후 초 수를 출력하는 데 사용 합니다. 그런 다음 뺄 연산의 간단한 문제입니다 $now으로부터 $future8만6천4백초 / 일에 의해 분할 :

#!/bin/bash

read -p "enter the date in the format YYYY-MM-DD "

future=$(date -d "$REPLY" "+%s")
now=$(date "+%s")
echo "$(( ( $future / 86400 ) - ( $now / 86400 ) )) days"


답변

함수를 awk사용하여에서 무언가를 시도해 볼 수 mktime있습니다.

awk '{print (mktime($0) - systime())/86400}'

awk는 “YYYY MM DD HH MM SS”형식으로 표준 입력에서 날짜를 읽은 다음 지정된 시간과 현재 시간의 차이를 일 단위로 인쇄합니다.

mktime단순히 지정된 형식의 시간을 참조 시간 (1970-01-01 00:00:00 UTC)에서 초 수로 변환합니다. systime simple은 현재 시간을 동일한 형식으로 지정합니다. 하나를 다른 것에서 빼면 몇 초 안에 얼마나 떨어져 있는지 알 수 있습니다. 86400 (24 * 60 * 60)으로 나누어 일로 변환합니다.


답변

여기에 루비 버전이 있습니다

require 'date'

puts "Enter a future date in format YYYY-MM-DD"
answer = gets.chomp

difference = (Date.parse(answer) - Date.today).numerator

puts difference > 1 ? "That day will come after #{difference} days" :
  (difference < 0) ? "That day passed #{difference.abs} days ago" :
 "Hey! That is today!"

실행 예 :

스크립트 실행 예 ruby ./day-difference.rb는 다음과 같습니다 (로 저장했다고 가정 day-difference.rb).

미래의 날짜로

$ ruby day-difference.rb
Enter a future date in format YYYY-MM-DD
2021-12-30
That day will come after 1848 days

날짜가 지났습니다

$ ruby day-difference.rb
Enter a future date in format YYYY-MM-DD
2007-11-12
That day passed 3314 days ago

오늘 날짜가 지났을 때

$ ruby day-difference.rb
Enter a future date in format YYYY-MM-DD
2016-12-8
Hey! That is today!

다음은 날짜의 차이를 확인할 수있는 멋진 웹 사이트입니다. http://www.timeanddate.com/date/duration.html


답변

dateutils날짜를 처리하는 매우 편리합니다 패키지. 여기에 대해 더 자세히 읽으십시오 github : dateutils

에 의해 설치

sudo apt install dateutils

간단히 말해서,

dateutils.ddiff <start date> <end date> -f "%d days"

여기서 출력은 초, 분,시, 일, 주, 월 또는 년으로 선택할 수 있습니다. 다른 작업에 출력을 사용할 수있는 스크립트에서 편리하게 사용할 수 있습니다.


예를 들어

dateutils.ddiff 2016-12-26  2017-05-12 -f "%m month and %d days"
4 month and 16 days

dateutils.ddiff 2016-12-26  2017-05-12 -f "%d days"
137 days


답변

awk Velor 라이브러리를 사용할 수 있습니다 .

$ velour -n 'print t_secday(t_utc(2018, 7, 1) - t_now())'
7.16478

또는:

$ velour -n 'print t_secday(t_utc(ARGV[1], ARGV[2], ARGV[3]) - t_now())' 2018 7 1
7.16477


답변

두 날짜가 같은 해에 속하면 간단한 해결책은 다음과 같습니다.

echo $((1$(date -d 2019-04-14 +%j) - 1$(date +%j)))

“% j”형식을 사용하여 연도를 기준으로 날짜 위치를 반환합니다 (예 : 현재 날짜의 경우 135). 반올림 문제를 피하고 과거의 날짜를 처리하여 부정적인 결과를 낳습니다.

그러나 연도 경계를 넘어 서면 실패합니다. 2 월 마지막이 지난 경우 매년 수동으로 365를 추가하거나 빼기 연도별로 366을 추가 (또는 빼기) 할 수 있지만 다른 솔루션과 거의 비슷합니다.

순수한 bash 솔루션은 다음과 같습니다.

#!/bin/bash
#
# Input sanitizing and asking for user input, if no date was given, is left as an exercise
# Suitable only for dates from 1.1.1970 to 31.12.9999
#
# Get date as parameter (in format yyyy-MM-dd
#
date2=$1
# for testing, more convenient:
# date2=2019-04-14
#
year2=${date2:0:4}
year1=$(date +%Y)
#
# difference in days, ignoring years:
# since %j may lead to values like 080..099, 
# which get interpreted as invalid octal numbers, 
# I prefix them with "1" each (leads to 1080..1099) 
daydiff=$((1$(date -d 1$date2 +%j)- $(date +%j)))
#
yeardiff=$((year2-year1))
# echo yeardiff $yeardiff
#
#
# summarize days per year, except for the last year:
#
daysPerYearFromTo () {
    year1=$1
    year2=$2
    days=0
    for y in $(seq $year1 $((year2-1)))
    do
        ((days+=$(date -d $y-12-31 +"%j")))
    done
    echo $days
}
# summarize days per year in the past, except for the last year:
#
daysPerYearReverse () {
    year1=$1
    year2=$2
    days=0
    for y in $(seq $((year1-1)) -1 $year2)
    do
        ((days+=$(date -d $y-12-31 +"%j")))
    done
    echo $days
}

case $yeardiff in
    0) echo $daydiff
        ;;
    # date in one of previous years:
    -[0-9]*) echo $((daydiff-$(daysPerYearReverse $year1 $year2)))
        ;;
    # date in one of future years:
    [0-9]*) echo $((daydiff+$(daysPerYearFromTo $year1 $year2)))
        ;;
esac

Shellcheck은 많은 따옴표를 제안하지만 9999 년을 초과하는 날에는 다른 접근법을 고려해야합니다. 과거에는 1970.01.01 이전의 날짜에 대해서는 자동으로 실패합니다. 사용자 입력 삭제는 사용자에게 연습으로 남습니다.

두 기능을 하나로 리팩토링 할 수 있지만 이해하기 어려울 수 있습니다.

스크립트는 과거의 윤년을 올바르게 처리하기 위해 철저한 테스트가 필요합니다. 나는 그것이 옳다는 것을 내기하지 않을 것입니다.