एक साधारण स्ट्रिंग से एक समयबद्ध वस्तु का निर्माण कैसे करें


96

मैं एक फ़ंक्शन लिख रहा हूं जिसे एक स्ट्रिंग के रूप में पारित करने के लिए टाइमडेल्टा इनपुट की आवश्यकता है। उपयोगकर्ता को "32m" या "2h32m", या यहां तक ​​कि "4:13" या "5hr34m56s" जैसे कुछ भी दर्ज करना होगा ... क्या कोई पुस्तकालय है या ऐसा कुछ है जिसमें इस तरह की चीज़ पहले से लागू है?


एक लाइन (आयात करने के बाद ) का उपयोग करते हुए लोगों के लिए बस dदिन, hघंटे, mमिनट और sसेकंड का समयबद्ध वस्तु का निर्माण करना चाहते हैं :। datetimedatetime.timedelta(days = d, hours = h, minutes=m, seconds=s)
zthomas.nc

जवाबों:


72

पहले प्रारूप (5hr34m56s) के लिए, आपको नियमित अभिव्यक्ति का उपयोग करके पार्स करना चाहिए

यहाँ फिर से आधारित समाधान है:

import re
from datetime import timedelta


regex = re.compile(r'((?P<hours>\d+?)hr)?((?P<minutes>\d+?)m)?((?P<seconds>\d+?)s)?')


def parse_time(time_str):
    parts = regex.match(time_str)
    if not parts:
        return
    parts = parts.groupdict()
    time_params = {}
    for (name, param) in parts.iteritems():
        if param:
            time_params[name] = int(param)
    return timedelta(**time_params)


>>> from parse_time import parse_time
>>> parse_time('12hr')
datetime.timedelta(0, 43200)
>>> parse_time('12hr5m10s')
datetime.timedelta(0, 43510)
>>> parse_time('12hr10s')
datetime.timedelta(0, 43210)
>>> parse_time('10s')
datetime.timedelta(0, 10)
>>> 

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

2
मैं फिर से आधारित समाधान उदाहरण :) जोड़ा
virhilo

4
मैं नहीं देखता कि कैसे dateutil.parser.parse अवधि को पार्स कर सकता है, ऐसा लगता है जैसे यह हमेशा एक डेटाइम रिटर्न करता है। मैं क्या खो रहा हूँ?
निकोलय

7
dateutil.parser.parsetimedeltaवस्तुओं को पार्स नहीं करेंगे । यह रिटर्न करता है datetime, और यह जैसे तार के लिए एक अपवाद को ट्रिगर करेगा '28:32:11.10'
Spak

95

मेरे लिए सबसे सुरुचिपूर्ण समाधान, बाहरी पुस्तकालयों जैसे कि डेटुतिल या मैन्युअल रूप से इनपुट पार्स करने के लिए सहारा के बिना, डेटाइम के शक्तिशाली strptimeस्ट्रिंग पार्सिंग विधि का उपयोग करना है।

from datetime import datetime, timedelta
# we specify the input and the format...
t = datetime.strptime("05:20:25","%H:%M:%S")
# ...and use datetime's hour, min and sec properties to build a timedelta
delta = timedelta(hours=t.hour, minutes=t.minute, seconds=t.second)

इसके बाद आप अपने टाइमडेल्टा ऑब्जेक्ट को सामान्य रूप से उपयोग कर सकते हैं, यह सुनिश्चित करने के लिए सेकंड में कनवर्ट करें कि हमने सही काम किया है आदि।

print(delta)
assert(5*60*60+20*60+25 == delta.total_seconds())

33
ध्यान दें कि यह केवल तभी काम करता है जब समय 24 घंटे से कम हो ( datetime.strptime("32:20:25","%H:%M:%S")काम नहीं करता है), और आपको सटीक इनपुट प्रारूप जानना होगा।
वर्धमानाल्ड

यह भी केवल ओपी के सवाल का जवाब देता है। यदि फ़ंक्शन को कई स्वरूपों से निपटने की आवश्यकता है - आपको अभी भी अतिरिक्त प्रारूप निरीक्षण (1 कॉलोन या 2?) की आवश्यकता है।
डैनी स्टेपल

3
@verdesmarald तो, अजगर 3.5 के रूप में, क्या बाहरी पुस्तकालयों का उपयोग किए बिना एक सुरुचिपूर्ण समाधान है और बिना मान के 24 घंटे से कम है?
अधिकतम

1
मुझे लगता है कि timedeltaबहुत कष्टप्रद पैरामीटर के लिए नामित मापदंडों को मैन्युअल रूप से निर्दिष्ट करने की आवश्यकता है , लेकिन सबसे अच्छा मैं इससे बचने के लिए आ सकता हूं:: delta = t - datetime.combine(t.date(), time.min), जो ... भयानक है।
काइल स्ट्रैंड

2
इस दृष्टिकोण के साथ एक गंभीर समस्या यह है कि यदि आप दिन शामिल करते हैं, तो% d को स्ट्रैप्टम में भेजना, आपको इनपुट दिवस 0 में सक्षम नहीं करेगा, क्योंकि दिनांक के लिए केवल> = 1 दिन मान्य हैं।
user1581390

75

मेरे हाथों में कल थोड़ा समय था, इसलिए मैंने पायथन मॉड्यूल में @virhilo के उत्तर को विकसित किया, @priestc द्वारा अनुरोध किए गए उन सभी सहित कुछ और समय के अभिव्यक्ति प्रारूप जोड़े

कोई भी व्यक्ति जो चाहता है, उसके लिए स्रोत कोड github (MIT लाइसेंस) पर है। यह PyPI पर भी है:

pip install pytimeparse

कई सेकंड के रूप में समय लौटाता है:

>>> from pytimeparse.timeparse import timeparse
>>> timeparse('32m')
1920
>>> timeparse('2h32m')
9120
>>> timeparse('4:13')
253
>>> timeparse('5hr34m56s')
20096
>>> timeparse('1.2 minutes')
72

वहाँ एक जावा / स्काला समकक्ष है?
luca.giovagnoli

बहुत बढ़िया! बहुत बहुत धन्यवाद
बाउंसर

@ luca.giovagnoli स्काला में आप अवधि वर्ग का उपयोग कर सकते हैं। अवधि का निर्माण '15 सेकंड ',' 4 मिनट 'आदि जैसे तारों से किया जा सकता है
कोनराड मलिक

14

मैं सिर्फ एक बार इनपुट करना चाहता था और फिर इसे विभिन्न तारीखों में जोड़ता था ताकि मेरे लिए यह काम करे:

from datetime import datetime as dtt

time_only = dtt.strptime('15:30', "%H:%M") - dtt.strptime("00:00", "%H:%M")

dtt.strptime(myduration, "%H:%M:%S") - dtt(1900, 1, 1)यह भी काम करता है ...
576i

8

मैंने कुछ उन्नयन के साथ विहिलो के अच्छे उत्तर को संशोधित किया है :

  • एक जोर दिया कि स्ट्रिंग एक वैध समय स्ट्रिंग है
  • "एच" के साथ "घंटा" घंटे-संकेतक को बदलें
  • एक "डी" दिनों के सूचक के लिए अनुमति दें
  • गैर-पूर्णांक समय की अनुमति दें (उदाहरण के 3m0.25sलिए 3 मिनट, 0.25 सेकंड)

import re
from datetime import timedelta


regex = re.compile(r'^((?P<days>[\.\d]+?)d)?((?P<hours>[\.\d]+?)h)?((?P<minutes>[\.\d]+?)m)?((?P<seconds>[\.\d]+?)s)?$')


def parse_time(time_str):
    """
    Parse a time string e.g. (2h13m) into a timedelta object.

    Modified from virhilo's answer at https://stackoverflow.com/a/4628148/851699

    :param time_str: A string identifying a duration.  (eg. 2h13m)
    :return datetime.timedelta: A datetime.timedelta object
    """
    parts = regex.match(time_str)
    assert parts is not None, "Could not parse any time information from '{}'.  Examples of valid strings: '8h', '2d8h5m20s', '2m4s'".format(time_str)
    time_params = {name: float(param) for name, param in parts.groupdict().items() if param}
    return timedelta(**time_params)

1
महान! मैंने "* 1d 3h 5m" की अनुमति देने के तत्वों के बीच "*" को जोड़ा
Marcel Waldvogel

@MarcelWaldvogel अच्छा है, अगर आप नए रेगेक्स के पाठ की नकल करते हैं तो मैं आपका जवाब जोड़ दूंगा
पीटर

@virhilo और पीटर: आपके कोड पर मेरा मामूली विकास यहाँ है: github.com/zeitgitter/zeitgitterd/blob/master/zeitgitter/… । मुझे लगता है कि अपने कोड का उपयोग करना ठीक है। क्या आपके पास लाइसेंस के लिए कोई प्राथमिकता है? MIT, Apache, GPL,…?
मार्सेल वाल्डवोगेल

1
मार्सेल, क्या आप मुझे अपना पता भेज सकते हैं ताकि मैं मुकदमा कर सकूं? जेके आगे जाओ कोई भी लाइसेंस ठीक है।
पीटर

यहाँ नया रेगेक्स है; अंतर है "*" s: regex = re.compile (r '^ ((? P <days> [\ _। d] +?) d)? *' r '((? P <hours>] \ _ । \ d] +?) h)? * 'r' ((? P <मिनट> [\ _। d d + +?) m)? * 'r' ((? p <seconds>] [\ _। d] +?) s)। $ ')
मार्सेल वाल्डवोगेल

3

यदि आप पायथन 3 का उपयोग करते हैं, तो यहां हरि शंकर के समाधान के लिए अद्यतन संस्करण, जिसका मैंने उपयोग किया है:

from datetime import timedelta
import re

regex = re.compile(r'(?P<hours>\d+?)/'
                   r'(?P<minutes>\d+?)/'
                   r'(?P<seconds>\d+?)$')

def parse_time(time_str):
    parts = regex.match(time_str)
    if not parts:
        return
    parts = parts.groupdict()
    print(parts)
    time_params = {}
    for name, param in parts.items():
        if param:
            time_params[name] = int(param)
    return timedelta(**time_params)

3

Django उपयोगिता फ़ंक्शन के साथ आता है parse_duration()। से प्रलेखन :

एक स्ट्रिंग पार्स करता है और एक लौटता है datetime.timedelta

"DD HH:MM:SS.uuuuuu"आईएसओ 8601 (जैसे P4DT1H15M20Sजो इसके बराबर है 4 1:15:20) या पोस्टग्रेएसक्यूएल के दिन-अंतराल अंतराल प्रारूप (जैसे 3 days 04:05:06) द्वारा निर्दिष्ट प्रारूप में डेटा की अपेक्षा करता है ।


1

आईएसओ 8601 अवधि स्ट्रिंग को पार्स करने के लिए आइसोडेट लाइब्रेरी का उपयोग करें । उदाहरण के लिए:

isodate.parse_duration('PT1H5M26S')

यह भी देखें कि क्या आईएसओ 8601 की अवधि को समयबद्धता में बदलने का एक आसान तरीका है?

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