string conversion to hours and minutes (not pandas standard time) - python

Lets say for e.g., I have (series) data in string format (e.g., '225586:47'). I want the machine to understand that this denotes hours and minutes.
Any idea how achieve this?

import pandas as pd
#this function will split a string, and treat each part as a part of a time
#then return seconds as an integer
def get_secs(time_str): #assumes string is in format HH:MM
h, m = time_str.split(':')
return int(h) * 3600 + int(m) * 60 #convert everything into seconds
#This function will take seconds and convert into a string
#in the format of "HH:MM"
#Note that if there are fractions of a minute, these will be rounded down to make MM an integer
def get_hhmm(secs):
hours = secs / (3600) #get the hours from seconds
minutes = (hours - int(hours)) * (60) # remainder as minutes
return "%02i:%02i" % (hours, minutes) #we have to integer-ize both of these since they are each floats
#dummy series
s = pd.Series(['10:20', '20:30', '30:40', '40:50', '50:60'])
#apply this function to the elements of your series
s = s.apply(get_secs)
#sum them
sum(s) #as seconds
sum(s)/60 #as minutes
sum(s)/60/60 #as hours
print(get_hhmm(sum(s))) #as an "hh:mm" string

I split the string based on the ":", took the first part, converted it to integer and multiplied it by 60. Took the second part, converted it to integer and added to the product that I got from the first part.
Did this for the entire column, added the values, divided by 60 to get hours and minutes.

Related

How do I convert integer into a time format

How would I go about converting a float like 3.65 into 4 mins 5 seconds.
I have tried using:
print(datetime.datetime.strptime('3.35','%M%-S'))
However, I get this back:
ValueError: '-' is a bad directive in format '%-M:%-S'
Take a look at the following script, you can figure out how to make it work for days years, etc, this only works if we assume the format is "hours.minutes"
import datetime
# Assuming the 3 represents the hours and the 0.65 the minutes
number = 3.65
# First, we need to split the numbero into its whole decimal part
# and its decimal part
whole_decimal_part = hours = int(number) # 3
decimal_part = number % whole_decimal_part # 0.6499999
# Now, we need to know how many extra hours are in the decimal part
extra_hours = round((decimal_part * 100) / 60) # 1
minutes = round((decimal_part * 100) % 60) # 5
hours += extra_hours # 4
time_str = "%(hours)s:%(minutes)s" % {
"hours": hours,
"minutes": minutes
} # 4:5
final_time = datetime.datetime.strptime(time_str, "%H:%M").time()
print(final_time) # 04:05:00
First, you should complain to whoever is giving you time data expressed like that.
If you need to process minutes and seconds as a standalone value, then the datetime object may not your best choice either.
If you still need to convert "3.65" into a datetime object corresponding to "4-05" you could adjust it to be a valid time representation before passing it to strptime()
m,s = map(int,"3.65".split("."))
m,s = (m+s)//60,s%60
dt = datetime.datetime.strptime(f"{m}-{s}","%M%-S")
Split your time into minute and seconds
If seconds is 60 or more, then add extra minutes (//) ; second is the modulo (%)
t="3.65"
m, s = [int(i) for i in t.split('.')]
if s >= 60:
m += s//60
s = s % 60
print(f'{m} mins {s} seconds') # -> 4 mins 5 seconds
while 65 seconds cannot be parsed correctly so you have to manipulate by yourself to clean the data first before parsing.
NOTE: assuming seconds is not a very very big number which can make minutes>60
import datetime
time= '3.65'
split_time = time.split(".")
minute =int(split_time[0])
seconds = int(split_time[1])
minute_offset, seconds = divmod(seconds, 60);
minute = int(split_time[0]) + minute_offset
print(datetime.datetime.strptime('{}.{}'.format(minute,seconds),'%M.%S')) #1900-01-01 00:04:05
You can alternatively use .time() on datetime object to extract the time
print(datetime.datetime.strptime('{}.{}'.format(minute,seconds),'%M.%S').time()) #00:04:05
A much cleaner and safer solution is (to consider hour as well). Convert everything into seconds and then convert back to hours, minutes, seconds
def convert(seconds):
min, sec = divmod(seconds, 60)
hour, min = divmod(min, 60)
return "%d:%02d:%02d" % (hour, min, sec)
time='59.65'
split_time = time.split(".")
minute =int(split_time[0])
seconds = int(split_time[1])
new_seconds = minute*60 +65
datetime.datetime.strptime(convert(new_seconds),'%H:%M:%S').time()

How to get a period of time with Numpy?

If a np.datetime64 type data is given, how to get a period of time around the time?
For example, if np.datetime64('2020-04-01T21:32') is given to a function, I want the function to return np.datetime64('2020-04-01T21:30') and np.datetime64('2020-04-01T21:39') - 10 minutes around the given time.
Is there any way to do this with numpy?
Numpy does not have a built in time period like Pandas does.
If all you want are two time stamps the following function should work.
def ten_minutes_around(t):
t = ((t.astype('<M8[m]') # Truncate time to integer minute representation
.astype('int') # Convert to integer representation
// 10) * 10 # Remove any sub 10 minute minutes
).astype('<M8[m]') # convert back to minute timestamp
return np.array([t, t + np.timedelta64(10, 'm')]).T
For example:
for t in [np.datetime64('2020-04-01T21:32'), np.datetime64('2052-02-03T13:56:03.172')]:
s, e = ten_minutes_around(t)
print(s, t, e)
gives:
2020-04-01T21:30 2020-04-01T21:32 2020-04-01T21:40
2652-02-03T13:50 2652-02-03T13:56:03.172 2652-02-03T14:00
and
ten_minutes_around(np.array([
np.datetime64('2020-04-01T21:32'),
np.datetime64('2652-02-03T13:56:03.172'),
np.datetime64('1970-04-01'),
]))
gives
array([['2020-04-01T21:30', '2020-04-01T21:40'],
['2652-02-03T13:50', '2652-02-03T14:00'],
['1970-04-01T00:00', '1970-04-01T00:10']], dtype='datetime64[m]')
To do so we can get the minute from the given time and subtract it from the given time to get the starting of the period and add 9 minutes to get the ending time of the period.
import numpy as np
time = '2020-04-01T21:32'
dt = np.datetime64(time)
base = (dt.tolist().time().minute) % 10 // base would be 3 in this case
start = dt - np.timedelta64(base,'m')
end = start + np.timedelta64(9,'m')
print(start,end,sep='\n')
I hope this helps.

How do I turn a number into a date?

I have a dataset with the dates given in numbers from 1995 to 2016.
1/1/1995 is equal to 1, 2/1/1995 is 2 and 31/12/2016 is 8036, so every day is one number.
How do I turn my time array [1,2,3,...,8034,8035,8036] into dates of dd/mm/yyyy?
Use the datetime.fromordinal(x) method. This creates a date from the number x, signifying the number of days since 0001-01-01.
If you want to start with x==1 being 1995-01-01, you can do
d = datetime.date(1,1,1) # actual date does not matter
print d.fromordinal( datetime.date(1994,12,31).toordinal() + x)
where x is the number of days since the last day of 1994.
Use the epoch conversion which is also supported by the python time library. The unix epoch time starts on 01/01/1970 and is counted in seconds. If you add 788932800 seconds to reach 01/01/1995, you can then add 86400 (seconds per day) and can use standard techniques to calculated the "seconds from epoch" back to a correct date.
Example code:
#!/usr/bin/python
import time
entryid = 5
epochdate = 788932800 + entryid * 86400
print time.strftime("%d/%m/%y", time.gmtime(epochdate))
does this help for first 100 days? You can change the no though.
import time
epochOne = 788918400 #epoch for 1995-01-01 00:00:00
oneDay = 86400 #epoch for 86400
noOfDays = 8036
for each in range(noOfDays):
epochEach = epochOne + (each * oneDay)
print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(epochEach)))

Python get hours, minutes, and seconds from time interval

I have timestamps that are calculated by a given interval. Ex: timestamp being 193894 and interval being 20000. The time is calculated by doing 193894/20000 = 9.6947. 9.6947 being 9 minutes and 0.6947 of a minute in seconds (0.6947 * 60) = 42 s (rounded up) thus the human readable timestamp being 9 min 42 sec.
Is there a Pythonic (assuming there is some library) way of doing this rather than doing a silly math calculation like this for every timestamp?
The reason being is because if timestamp is 1392338 (1 hour 9 min 37 sec) something that yields in the hours range, I want to be able to keep it dynamic.
I am just wondering if there was a better way to do this than the mathematical calculation way.
The linked question can help you actually format timedelta object once you have it, but there are a few tweaks you need to make to get the exact behavior you want
from __future__ import division
from datetime import timedelta
from math import ceil
def get_interval(timestamp, interval):
# Create our timedelta object
td = timedelta(minutes=timestamp/interval)
s = td.total_seconds()
# This point forward is based on http://stackoverflow.com/a/539360/2073595
hours, remainder = divmod(s, 3600)
minutes = remainder // 60
# Use round instead of divmod so that we'll round up when appropriate.
# To always round up, use math.ceil instead of round.
seconds = round(remainder - (minutes * 60))
return "%d hours %d min %d sec" % (hours, minutes, seconds)
if __name__ == "__main__:
print print_interval(1392338, 20000)
print get_interval(193894, 20000)
Output:
1 hours 9 min 37 sec
0 hours 9 min 42 sec

Calculating difference in seconds between two dates not working above a day

I have a function that accepts a date and returns the difference in time between then and the current time (in seconds). It works fine for everything less than a day. But when I even enter a date that's a year in the future, it still returns a number around 84,000 seconds (there are around 86,400 seconds in a day).
def calc_time(date):
future_date = str(date)
t_now = str(datetime.utcnow())
t1 = datetime.strptime(t_now, "%Y-%m-%d %H:%M:%S.%f")
t2 = datetime.strptime(future_date, "%Y-%m-%d %H:%M:%S.%f")
return ((t2-t1).seconds)
Even when I run it with a parameter whose date is in 2014, i get a number way too low.
Anyone have any insight?
Reading the datetime.timedelta docs.
All arguments are optional and default to 0. Arguments may be ints,
longs, or floats, and may be positive or negative.
Only days, seconds and microseconds are stored internally. Arguments
are converted to those units:
A millisecond is converted to 1000 microseconds. A minute is converted
to 60 seconds. An hour is converted to 3600 seconds. A week is
converted to 7 days. and days, seconds and microseconds are then
normalized so that the representation is unique, with
0 <= microseconds < 1000000 0 <= seconds < 3600*24 (the number of
seconds in one day)
-999999999 <= days <= 999999999
The solution is to use .total_seconds() instead of .seconds
The following code will return you the number of days between the two given dates
$daysremaining = ceil(abs(strtotime($yourdate) - strtotime($currentdate)) / 86400);
and to get the difference in seconds use
$secondsremaining = strtotime($yourdate) - strtotime($currentdate);
upvote if useful
ahh. apparently .seconds will only return the difference of seconds within the range of a day.
.seconds will include both hours and minutes, so i needed to add that to .days*86400 to get total seconds.
thanks for the help, everyone! ;D

Categories