脚本或函数返回从现在到给定日期有多少天

脚本或函数返回从现在到给定日期有多少天

我想编写一个脚本或函数来告诉我从现在到未来某个日期还有多少天。我正在努力解决的是如何处理给定的日期并将其与当前日期进行比较……我想象着类似

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

然后我假设我有一个对 shell 来说毫无意义的字符串,我必须做一些评估,比如……??(这只是一个例子;我想是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))   

我肯定是让自己太为难了;可能有一个文本处理工具可以理解日期并可以比较它们。

我怎样才能做到这一点?

答案1

纪元时间

一般来说,如果我们首先将时间转换为(Unix)的话,时间计算是最容易的时代时间(距 1970 年 1 月 1 日的秒数)。在 Python 中,我们有工具可以将时间转换为纪元时间,并转换回我们喜欢的任何日期格式。

我们可以简单地设置一种格式,例如:

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

...如上所述,这是自 1970 年 1 月 1 日以来的秒数

计算两个日期之间的天数

如果我们在今天和未来的日期都这样做,则随后计算差值:

#!/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
    

    设置脚本的实际路径...

答案2

GNUdate实用程序在这方面相当擅长。它能够解析各种日期格式,然后以另一种格式输出。这里我们使用%s输出自纪元以来的秒数。然后$now从中减去$future并除以 86400 秒/天是一个简单的算术问题:

#!/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"

答案3

您可以尝试awk使用该mktime函数执行某些操作

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

awk 期望从标准输入中读取“YYYY MM DD HH MM SS”格式的日期,然后打印指定时间与当前时间之间的差值(以天为单位)。

mktime只是将时间(指定格式)转换为距参考时间(1970-01-01 00:00:00 UTC)的秒数;systime 仅以相同格式指定当前时间。将一个时间减去另一个时间,即可得到它们相差的秒数。除以 86400(24 * 60 * 60)即可转换为天数。

答案4

有一个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

相关内容