स्क्रिप्ट या फ़ंक्शन किसी दिए गए दिनांक तक कितने दिनों से वापस आने के लिए


28

मैं भविष्य में दी गई तारीख तक अब से कितने दिन पहले यह बताने के लिए एक स्क्रिप्ट या फंक्शन लिखना चाहूंगा। मैं वर्कआउट करने के लिए संघर्ष कर रहा हूं कि दी गई तारीख को कैसे प्रोसेस किया जाए और वर्तमान तारीख के साथ तुलना की जाए ... मैं कुछ इस तरह की कल्पना कर रहा हूं

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))   

मैं निश्चित रूप से इसे अपने लिए बहुत कठिन बना रहा हूं; शायद एक टेक्स्ट प्रोसेसिंग टूल है जो तारीखों को समझता है और उनकी तुलना कर सकता है।

मैं यह कैसे कर सकता हूँ?


शायद कोई अजगर? वैसे भी, समय को
युगांतर में

@JacobVlijm python समाधान पूरी तरह से आपका स्वागत है - जब मैं आखिरकार अजगर XD सीखने के लिए इधर-उधर हो जाऊंगा तो मुझे मदद मिलेगी और मैं चाहता हूं कि यह भी काम करे :)
Zanna

AHA, एक पल ...
याकूब Vlijm

जवाबों:


29

युगांतर काल

सामान्य तौर पर, समय पर गणना के लिए सबसे आसान कर रहे हैं अगर हम (यूनिक्स) में पहले परिवर्तित समय युग समय (1970/01/01 से सेकंड)। अजगर में, हमारे पास समय को युग में बदलने के लिए उपकरण होते हैं, और किसी भी तारीख प्रारूप में वापस आ जाते हैं जिसे हम पसंद करते हैं।

हम बस एक प्रारूप सेट कर सकते हैं, जैसे:

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))

यहाँ छवि विवरण दर्ज करें

... और ज़ेनिटी विकल्प

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

    स्क्रिप्ट के लिए वास्तविक पथ सेट करें ...


23

जीएनयू dateउपयोगिता बात की इस तरह से काफी अच्छा है। यह एक अच्छी किस्म के डेट फॉर्मेट और फिर दूसरे फॉर्मेट में आउटपुट देने में सक्षम है। यहाँ हम %sयुग के बाद से सेकंड की संख्या का उत्पादन करने के लिए उपयोग करते हैं । फिर 86400 सेकंड / दिन $nowसे घटाना $futureऔर विभाजित करना अंकगणित का एक साधारण मामला है:

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

गलत राउंडिंग के अलावा (ऐसा लगता है), यह अच्छी तरह से काम करता है! मुझे ग्नू तिथि की शक्तियों पर संदेह करने के लिए मूर्खतापूर्ण लगता है :) धन्यवाद :)
Zanna

1
@Zanna - मुझे लगता है कि अंतर को लेने से पहले गोलाई की समस्या का समाधान केवल 86400 तक दोनों टाइमस्टैम्प को विभाजित करना है। लेकिन कुछ विस्तार हो सकता है जो मैं यहां याद कर रहा हूं। क्या आप चाहते हैं कि प्रवेश की तारीख स्थानीय समय या यूटीसी हो? यदि इसका UTC है, तो -uपैरामीटर को इसमें जोड़ें date
डिजिटल ट्रॉमा

वे दिन जो सामान्य समय और दिन के समय की बचत के बीच स्विच करते हैं, वे +/- 1 घंटे के लिए भिन्न हो सकते हैं और शायद ही कभी कुछ दिनों में सुधार सेकंड हो। लेकिन व्यवहार में, यह ज्यादातर मामलों में महत्वहीन हो सकता है।
उपयोगकर्ता अज्ञात

10

आप फ़ंक्शन awkका उपयोग करके कुछ करने की कोशिश कर सकते हैंmktime

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

Awk "YYYY MM DD HH MM SS" प्रारूप में मानक इनपुट से तारीख पढ़ने की उम्मीद करता है और फिर दिनों में निर्दिष्ट समय और वर्तमान समय के बीच अंतर को प्रिंट करता है।

mktimeबस एक समय (निर्दिष्ट प्रारूप में) एक संदर्भ समय से सेकंड की संख्या (1970-01-01 00:00:00 यूटीसी) में कनवर्ट करता है; सिस्टाइम सरल उसी प्रारूप में वर्तमान समय को निर्दिष्ट करता है। एक को दूसरे से घटाएं और आप सेकंड में कितनी दूर हैं। दिनों में बदलने के लिए 86400 (24 * 60 * 60) से विभाजित करें।


1
अच्छा, फिर भी एक मुद्दा है: मुझे लगता है कि आप एक फ्लोट के रूप में दिनों की संख्या नहीं चाहते हैं, तो बस 86400 से विभाजित करने से काम नहीं चलेगा, समाधान के रूप में संभव गोलाई एक गलत आउटपुट देता है यदि आप 24 घंटे के पास हैं
जैकब व्लिजम

नोट Awk समय कार्य POSIX नहीं हैं
स्टीवन पेनी

10

यहाँ एक रूबी संस्करण है

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 के अंतर की जांच करने के लिए एक अच्छी वेबसाइट है


बहुत बढ़िया! इतना सरल और स्पष्ट। रूबी एक महान भाषा की तरह लगती है :)
Zanna

बहुत बढ़िया! रूबी में आपका स्वागत है :)
याकूब Vlijm

1
@ ज़नाना धन्यवाद। यह सचमुच में है। अगर आप 15 mintues मिला यहाँ tryruby । :)
अनवर

@JacobVlijm प्रोत्साहन के लिए धन्यवाद। हालाँकि मैं अभी भी एक छात्र हूँ :)
अनवर

6

एक 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

बहुत बढ़िया :) इस पैकेज के बारे में जानकर अच्छा लगा।
ज़न्ना


0

एक छोटा समाधान, यदि दोनों तिथियां एक ही वर्ष की हैं, तो:

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

"% j" -फॉर्मैट का उपयोग करते हुए, जो वर्ष में दिनों की तारीख की स्थिति को लौटाता है, अर्थात वर्तमान तिथि के लिए 135। यह चक्कर की समस्याओं से बचा जाता है और अतीत में तारीखों को संभालता है, नकारात्मक परिणाम देता है।

हालांकि, साल की सीमाओं को पार करते हुए, यह विफल हो जाएगा। आप प्रत्येक वर्ष के लिए या 366 प्रत्येक लीप वर्ष के लिए मैन्युअल रूप से जोड़ सकते हैं (या घटा सकते हैं), अगर फरवरी के आखिरी को पार कर लिया जाता है, लेकिन यह लगभग अन्य समाधानों की तरह ही होगा।

यहाँ शुद्ध बैश समाधान:

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

शेलचेक बहुत से दोहरे उद्धरण चिह्नों का सुझाव देता है, लेकिन वर्ष 9999 से अधिक दिनों के लिए आपको एक अलग दृष्टिकोण पर विचार करना चाहिए। अतीत के लिए, यह 1970.01.01 से पहले की तारीखों के लिए चुपचाप विफल हो जाएगा। उपयोगकर्ता इनपुट को सैनिटाइज़ करना उपयोगकर्ता को एक अभ्यास के रूप में छोड़ दिया जाता है।

दो कार्यों को एक में बदला जा सकता है, लेकिन यह समझना मुश्किल हो सकता है।

कृपया ध्यान दें, कि स्क्रिप्ट को अतीत में सही ढंग से छलांग लगाने के लिए संपूर्ण परीक्षण की आवश्यकता है। मैं शर्त लगा सकता हूं कि यह सही नहीं है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.