Convert fractional years to a real date in Python - python

How do I convert fractional years to a real date by using Python?
E. g. I have an array
[2012.343, 2012.444, 2012.509]
containing fractional years and I would like to get "yyyy-mm-dd hh:mm".

Here it`s a better solution, that give you the answer in datetime format.
from datetime import timedelta, datetime
def convert_partial_year(number):
year = int(number)
d = timedelta(days=(number - year)*365)
day_one = datetime(year,1,1)
date = d + day_one
return date
This solution doesnt count the extra day in leap years. If you need to do so, make a function is_leap(year) that returns a bool, and change my code to this:
from datetime import timedelta, datetime
def convert_partial_year(number):
year = int(number)
d = timedelta(days=(number - year)*(365 + is_leap(year)))
day_one = datetime(year,1,1)
date = d + day_one
return date
Check out datetime module. You can find a even better solution for your problem there.

import datetime as DT
def t2dt(atime):
"""
Convert atime (a float) to DT.datetime
This is the inverse of dt2t.
assert dt2t(t2dt(atime)) == atime
"""
year = int(atime)
remainder = atime - year
boy = DT.datetime(year, 1, 1)
eoy = DT.datetime(year + 1, 1, 1)
seconds = remainder * (eoy - boy).total_seconds()
return boy + DT.timedelta(seconds=seconds)
def dt2t(adatetime):
"""
Convert adatetime into a float. The integer part of the float should
represent the year.
Order should be preserved. If adate<bdate, then d2t(adate)<d2t(bdate)
time distances should be preserved: If bdate-adate=ddate-cdate then
dt2t(bdate)-dt2t(adate) = dt2t(ddate)-dt2t(cdate)
"""
year = adatetime.year
boy = DT.datetime(year, 1, 1)
eoy = DT.datetime(year + 1, 1, 1)
return year + ((adatetime - boy).total_seconds() / ((eoy - boy).total_seconds()))

You can determine the epoch time of Jan 1 of the year part. Add that to the fractional part times 365 * 24 * 60 * 60. Then convert your epoch time to a date time.
see Python: Converting Epoch time into the datetime

Related

How to subtract 2 hours from time formatted as string [duplicate]

This question already has answers here:
Subtract hours and minutes from time
(3 answers)
Closed last year.
My initial string looks like following:
a1 = "06:00:00"
a2 = "01:00:00"
I want to set the time back by two hours.
How to get the following output (in string format)?
a1_new = "04:00:00"
a2_new = "23:00:00"
Here you go!
from datetime import datetime, timedelta
a1 = "06:00:00"
x = datetime.strptime(a1, "%H:%M:%S") - timedelta(hours=2, minutes=0)
y = x.strftime("%H:%M:%S")
print(y)
Steps:
Convert HMS into a DateTime Object
Minus 2 hours from this
Convert the result into a String that only contains Hour Minute & Second
from datetime import datetime
from datetime import timedelta
time_fmt = "%H:%M:%S"
a1_new = datetime.strptime(a1, time_fmt) - timedelta(hours = 2)
a1_new = a1_new.strftime("%H:%M:%S")
print(a1_new)
'08:00:00'
I am assuming here that you only need a simple 24-hour clock.
s = "01:00:00"
h, m, s = s.split(":")
new_hours = (int(h) - 2) % 24
result = ':'.join((str(new_hours).zfill(2), m, s))
convert to datetime:
import datetime
a1 = "06:00:00"
obj = datetime.datetime.strptime(a1,"%H:%M:%S")
obj.replace(hour=obj.hour-2) #hours = hours - 2
tostr = obj.hour+":"+obj.min+":"+obj.second
print(tostr)
If your strings are always going to follow that exact format and you don't want to use datetime, here's a different way to do it: You could split the strings by their colons to isolate the hours, then work on them that way before joining back to a string.
a1 = "06:00:00"
parts = a1.split(":") # split by colons
hour = (int(parts[0]) - 2) % 24 # isolate hour, convert to int, and subtract hours, and clamp to our 0-23 bounds
parts[0] = f"{hour:02}" # :02 in an f-string specifies that you want to zero-pad that string up to a maximum of 2 characters
a1_new = ":".join(parts) # rejoin string to get new time
If there's any uncertainty in the format of the string however, this completely falls apart.
Convert to datetime, subtract timedelta, convert to string.
from datetime import datetime, timedelta
olds = ["06:00:00", "01:00:00"]
objs = [datetime.strptime(t, "%H:%M:%S") - timedelta(hours=2) for t in olds]
news = [t.strftime("%H:%M:%S") for t in objs]
You can use datetime and benefit from the parameters of datetime.timedelta:
from datetime import datetime, timedelta
def subtime(t, **kwargs):
return (datetime.strptime(t, "%H:%M:%S") # convert to datetime
- timedelta(**kwargs) # subtract parameters passed to function
).strftime("%H:%M:%S") # format as text again
subtime('01:00:00', hours=2)
# '23:00:00'
subtime('01:00:00', hours=2, minutes=62)
# '21:58:00'

How to convert numbers to dates

the emplyee number is composed of year and month and 3 digit control number how to know the number of years they works if we base on todays date? Employee1 201011003, eployee2 200605015
You can use datetime library like this:
from datetime import date
date_str = '201011003'
year = int(date_str[0:4])
month = int(date_str[4:6])
d = date(year, month, 1)
year_delta = (date.today() - d).days // 365
print(year_delta)
You can use datetime.strptime to read the date string into a datetime object. By subtracting two datetime objects you'll get back a timedelta object, which you can use to compute the years the employee has been there.
from datetime import datetime
def get_date(s):
return datetime.strptime(s[:6], '%Y%m')
Examples
>>> get_date('201011003')
datetime.datetime(2010, 11, 1, 0, 0)
>>> get_date('200605015')
datetime.datetime(2006, 5, 1, 0, 0)
Depending on the precision you want, you can approximate the number of years the employee has been there like
def get_years(s):
start = datetime.strptime(s[:6], '%Y%m')
now = datetime.now()
return (now - start).days / 365.25
>>> get_years('201011003')
9.527720739219713
>>> get_years('200605015')
14.03148528405202
To get very accurate results, I suggest you to use the dateutil package. It contains a super powerful function called relativedelta that is going to give you the years, months and days that have passed since the day you are interested in, considering leap years (instead of just days, as the datetime.timedelta does).
Also, just as CoryKramer did, we can use the strptime function to parse the date from the employee's codes you have.
import datetime as dt
from dateutil.relativedelta import relativedelta
employee = '201011003'
date_joined = dt.datetime.strptime(employee[:6], '%Y%m')
result = relativedelta(dt.datetime.today(), date_joined)
print('The employee has been working for {} years, {} months and {} days'.format(
result.years, result.months, result.days))
Outputs
The employee has been working for 9 years, 6 months and 11 days

python convert filetime to datetime for dates before 1970

I need to convert filetime to datetime. I am using this code filetime.py, from here as mentioned in this thread Datetime to filetime (Python).
In the code
EPOCH_AS_FILETIME = 116444736000000000 # January 1, 1970 as MS file time
HUNDREDS_OF_NANOSECONDS = 10000000
def filetime_to_dt(ft):
"""Converts a Microsoft filetime number to a Python datetime. The new datetime object is time zone-naive but is equivalent to tzinfo=utc.
>>> filetime_to_dt(116444736000000000)
datetime.datetime(1970, 1, 1, 0, 0)
"""
# Get seconds and remainder in terms of Unix epoch
(s, ns100) = divmod(ft - EPOCH_AS_FILETIME, HUNDREDS_OF_NANOSECONDS)
# Convert to datetime object
dt = datetime.utcfromtimestamp(s)
# Add remainder in as microseconds. Python 3.2 requires an integer
dt = dt.replace(microsecond=(ns100 // 10))
return dt
datetime.utcfromtimestamp does not take negative value on windows system, so I can't convert filetime before Jan 1st 1970. But I can convert dates before 1970 on Mac using the exact same code (reason here). Is there any workaround for windows?
By adding a timedelta to a reference date you can use any date formula you'd like. timedelta is allowed to be positive or negative.
def filetime_to_dt(ft):
us = (ft - EPOCH_AS_FILETIME) // 10
return datetime(1970, 1, 1) + timedelta(microseconds = us)
According to docs, you have to use:
dt = datetime.fromtimestamp(s, datetime.timezone.utc)
instead of:
dt = datetime.utcfromtimestamp(s)
first you need to convert it to a recognizable filetime format like this:
>>> dwLowDateTime = 0x0F7297A80
>>> dwHighDateTime = 0x1C3F10F << 32
>>> ft = (dwLowDateTime & 0xFFFFFFFF) | dwHighDateTime
127210265370000000
and then use this script, it converts filetime to datetime and vice versa https://gist.github.com/Mostafa-Hamdy-Elgiar/9714475f1b3bc224ea063af81566d873
>>> filetime_to_dt(ft)
2004-02-12 02:28:57
Use timedeltas to add/subtract/divide between time frames:
FILE_TIME_EPOCH = datetime.datetime(1601, 1, 1)
FILE_TIME_MICROSECOND = 10 # FILETIME counts 100 nanoseconds intervals = 0.1 microseconds, so 10 of those are 1 microsecond
def convert_from_file_time(file_time):
microseconds_since_file_time_epoch = file_time // FILE_TIME_MICROSECOND
return FILE_TIME_EPOCH + datetime.timedelta(microseconds=microseconds_since_file_time_epoch)
And the other side of this is:
def convert_to_file_time(date_time):
microseconds_since_file_time_epoch = (date_time - FILE_TIME_EPOCH) // datetime.timedelta(microseconds=1)
return microseconds_since_file_time_epoch * FILE_TIME_MICROSECOND

find the interval of a given date in python

I'm struggling with date objects in python.
I have the following data:
from datetime import datetime, timedelta
# date retrieved from a list
ini = [u'2016-01-01']
# transform the ini in a readable string
ini2 = ', '.join(map(str, ini))
# transform the string a date object
date_1 = datetime.strptime(ini2, "%Y-%m-%d")
# number that is the length of the date
l = 365.0
# adding l to ini2
final = date_1 + timedelta(days = l)
Now I'd need to split the whole interval (that is the period from date_1 to final) by an input number (e.g. ts = 4) and, given another input date (e.g. new_date = u'2016-05-19') check in which interval it is (in the example 19th of May is in t2 = 2).
I hope I made myself clear enough.
Thanks
I tried different approaches but none seems the right one.
This might help:
from datetime import datetime, timedelta
def which_interval(date0, delta, date1, n_intervals):
date0 = datetime.strptime(date0, '%Y-%m-%d')
delta = timedelta(days = delta)
date1 = datetime.strptime(date1, '%Y-%m-%d')
delta1 = date1 - date0
quadrile = int(((float(delta1.days) / delta.days) * n_intervals))
return quadrile
# Example: figure out which quarter August 1st is in
interval = which_interval(
'2016-01-01',
366,
'2016-08-01',
4)
print '2016-08-01 is in interval %d, Q%d'%(interval, interval+1)
Note that this function uses python indices so it will start at quarter 0 and end at quarter 3. If you want 1-based indices (so the answer will be 1, 2, 3, or 4) you would want to add 1 to the result.
the timedelta object supports division, so use floor division by a step and you will get an interval in range(ts)
new_date = datetime.strptime(u'2016-05-19', "%Y-%m-%d")
ts = 4
step = timedelta(days=l)/ts #divide by the number of steps
interval = (new_date - date_1)//step #get the number this interval is in
so for date_1 <= new_date < date_1 + step interval will be 0, for date_1+step<=new_date < date_1 + step*2 interval will be 1, etc.
This of course is using python style indices so to get the number starting from 1, add one:
interval = (new_date - date_1)//step + 1
EDIT: the functionality to divide timedelta objects was only added in python3, you would need to use the .total_seconds() method to do the calculation in python 2:
step = timedelta(days=l).total_seconds()/ts #divide by inteval
interval = (new_date - date_1).total_seconds()//step
You could calculate this using the seconds total of the intervals.
import math
from datetime import datetime, timedelta
l = 365.0
factor = 4
date_1 = datetime.strptime('2016-01-01', "%Y-%m-%d")
lookup_dt = datetime.strptime('2016-12-01', "%Y-%m-%d")
def get_interval_num(factor, start_dt, td, lookup_dt):
final = start_dt + td
interval = (final - start_dt).total_seconds()
subinterval = interval / factor
interval_2 = (lookup_dt - start_dt).total_seconds()
return int(math.ceil(interval_2 / subinterval))
num = get_interval_num(
factor=factor,
start_dt=date_1,
td= timedelta(days=l),
lookup_dt=lookup_dt
)
print("The interval number is: %s" % num)
Output would be:
The interval number is: 4
EDIT: clearified variable naming, extended code snippet

calculate difference between two time in hour

I want to calculate difference between two time in hours using django in sql db the time are stored in timefield.
I tried this:
def DesigInfo(request): # attendance summary
emplist = models.staff.objects.values('empId', 'name')
fDate = request.POST.get('fromDate')
tDate = request.POST.get('toDate')
if request.GET.get('empId_id'):
sel = attendance.objects.filter(empId_id=request.GET.get('empId_id'),)
for i in sel:
# print i.
# print i.outTime
# print i.inTime.hour,i.inTime.minute,i.inTime.second - i.outTime.hour,i.outTime.minute,i.outTime.second
ss = i.inTime.hour
ss1 = 12 - ss
mm = i.outTime.hour
mm1 = (12 + mm) - 12
print ss1 + mm1
Since i.inTime and i.outTime are time objects you cannot simply subtract them. A good approach is to convert them to datetime adding the date part (use today() but it is irrelevant to the difference), then subtract obtaining a timedelta object.
delta = datetime.combine(date.today(), i.outTime) - datetime.combine(date.today(), i.inTime)
(Look here: subtract two times in python)
Then if you want to express delta in hours:
delta_hours = delta.days * 24 + delta.seconds / 3600.0
A timedelta object has 3 properties representing 3 different resolutions for time differences (days, seconds and microseconds). In the last expression I avoided to add the microseconds but I suppose it is not relevant in your case. If it is also add delta.microseconds / 3600000000.0
Note that simply dividing seconds by 3600 would have returned only the integer part of hours avoiding fractions. It depends on your business rules how to round it up (round, floor, ceil or leave the fractional part as I did)
Using datetime objects: https://docs.python.org/2/library/datetime.html
A good stack overflow post on the topic How to get current time in Python
from datetime import datetime
now = datetime.now()
# wait some time
then = ... some time
# diff is a datetime.timedelta instance
diff = then - now
diff_hours = diff.seconds / 3600
You might want to play with this codes:
from datetime import datetime
#set the date and time format
date_format = "%m-%d-%Y %H:%M:%S"
#convert string to actual date and time
time1 = datetime.strptime('8-01-2008 00:00:00', date_format)
time2 = datetime.strptime('8-02-2008 01:30:00', date_format)
#find the difference between two dates
diff = time2 - time1
''' days and overall hours between two dates '''
print ('Days & Overall hours from the above two dates')
#print days
days = diff.days
print (str(days) + ' day(s)')
#print overall hours
days_to_hours = days * 24
diff_btw_two_times = (diff.seconds) / 3600
overall_hours = days_to_hours + diff_btw_two_times
print (str(overall_hours) + ' hours');
''' now print only the time difference '''
''' between two times (date is ignored) '''
print ('\nTime difference between two times (date is not considered)')
#like days there is no hours in python
#but it has seconds, finding hours from seconds is easy
#just divide it by 3600
hours = (diff.seconds) / 3600
print (str(hours) + ' Hours')
#same for minutes just divide the seconds by 60
minutes = (diff.seconds) / 60
print (str(minutes) + ' Minutes')
#to print seconds, you know already ;)
print (str(diff.seconds) + ' secs')
The easiest way through I achieve is the comment of Zac given above. I was using relativedelta like this
from dateutil import relativedelta
difference = relativedelta.relativedelta( date1, date2)
no_of_hours = difference.hours
but it did not give me correct result when the days changes. So, I used the approach expressed above:
no_of_hours = (difference.days * 24) + (difference.seconds / 3600)
Please note that you will be getting negative value if date2 is greater than date1. So, you need to swipe the position of date variables in relativedelta.

Categories