Home > Back-end >  Convert date with more than 31 days to regular date format in python
Convert date with more than 31 days to regular date format in python

Time:03-18

I have exported some data from another programm, where I added up time for a station waiting. So after some time, I have the format '32:00:00:33.7317' for the waiting time.

This is my function to convert every date into the format I want:

def Datum_formatieren(Datensatz):
    if len(str(Datensatz)) == 24:
        return datetime.datetime.strptime(Datensatz, "%d.%m.%Y %H:%M:%S.%f").strftime("%d%H%M")
    elif len(str(Datensatz)) == 3:
        return 0
        #return datetime.datetime.strptime(Datensatz, "%S.%f").strftime("%d%H%M")
    elif len(str(Datensatz)) == 5:
        return str(Datensatz)
    elif len(str(Datensatz)) == 7:
        return str(Datensatz)
    elif len(str(Datensatz)) == 6:
        return datetime.datetime.strptime(str(Datensatz), "%S.%f").strftime("%d%H%M")
    elif len(str(Datensatz)) == 9 or len(str(Datensatz))==10:
        return datetime.datetime.strptime(str(Datensatz), "%M:%S.%f").strftime("%d%H%M")
    elif len(str(Datensatz)) == 12 or len(str(Datensatz)) ==13:
        return datetime.datetime.strptime(str(Datensatz), "%H:%M:%S.%f").strftime("%d%H%M")
    elif len(str(Datensatz)) == 15 or len(str(Datensatz)) == 16:
        return datetime.datetime.strptime(str(Datensatz), "%d:%H:%M:%S.%f").strftime("%d%H%M")

I get the following error since python does not recognize days above 30 or 31:

ValueError: time data '32:00:00:33.7317' does not match format '%d:%H:%M:%S.%f'

How do I convert all entries with days above 31 into a format, which python can recognize?

CodePudding user response:

You are misusing datetime wich only map to correct dates with times - not "any amount time passed".

Use a timedelta instead:

Adapted from datetime.timedelta:

from datetime import datetime, timedelta
delta = timedelta( days=50, seconds=27, microseconds=10, 
                   milliseconds=29000, minutes=5, hours=8, weeks=2 )

print(datetime.now()   delta)

You can add any timedelta to a normal datetime and get the resulting value.


If you want to stick wich your approach you may want to shorten it:

 if len(str(Datensatz)) == 9 or len(str(Datensatz))==10:
 if len(Datensatz) in (9,10):

Related: How to construct a timedelta object from a simple string (look at its answers and take inspiration with attribution from it)

CodePudding user response:

  • You're taking the Datensatz variable, converting it to string using str(), then parsing it back into an internal representation; there is almost always a better way to do it.

    Can you check what type the Datensatz variable has, perhaps print(type(Datensatz)) or based on the rest of your code?

    Most likely the Datensatz variable already has fields for the number of days, hours, minutes and seconds. It's usually much better to base your logic on those directly, rather than converting to string and back.

  • As others have pointed out, you're trying to use a datetime.datetime to represent a time interval; this is incorrect. Instead, you need to either:

    • Use the datetime.timedelta type, which is designed for time intervals. It can handle periods over 30 days correctly:

      >>> print(datetime.timedelta(days=32, seconds=12345))
      32 days, 3:25:45
      >>> 
      
    • Since your function is named Datum_formatieren, perhaps you intend to take Datensatz and convert it to string, for output to the user or to another system.

      In that case, you should take the fields directly in Datensatz and convert them appropriately, perhaps using f-strings or % formatting. Depending on the situation, you may need to do some arithmetic. The details will depend on the type of Datensatz and the format you need on the output.

CodePudding user response:

You cannot use datetime.datetime.strptime() to construct datetimes that are invalid - why see other answer.

You can however leverage datetime.timespan:

import datetime 

def Datum_formatieren(Datensatz):        
    # other cases omitted for brevity

    # Input:  "days:hours:minutes:seconds.ms"
    if len(Datensatz) in (15,16):
        k = list(map(float,Datensatz.split(":")))
        secs = k[0]*60*60*24   k[1]*60*60   k[2]*60   k[3]  
        td = datetime.timedelta(seconds=secs)
        days = td.total_seconds() / 24 / 60 // 60
        hours = (td.total_seconds() - days * 24*60*60) / 60 // 60
        minuts = (td.total_seconds() - days *24*60*60 - hours * 60*60) // 60
        print(td)
        return f"{td.days}{int(hours):02d}{int(minuts):02d}"

print(Datum_formatieren("32:32:74:33.731"))

Output for "32:32:74:33.731":

33 days, 9:14:33.731000   # timespan
330914                    # manually parsed
  • Related