Python convert datetime.time to arrow - python

I need to convert a python object datetime.time to an arrow object.
y = datetime.time()
>>> y
datetime.time(0, 0)
>>> arrow.get(y)
TypeError: Can't parse single argument type of '<type 'datetime.time'>'

Arrow follows a specific format, as specified in its documentation:
arrow.get('2013-05-11T21:23:58.970460+00:00')
you need to convert your datetime object to arrow-understandable format in order to be able to convert it to an arrow object. the codeblock below should work:
from datetime import datetime
import arrow
arrow.get(datetime.now())

A datetime.time object holds "An idealized time, independent of any particular day". Arrow objects cannot represent this kind of partial information, so you have to first "fill it out" with either today's date or some other date.
from datetime import time, date, datetime
t = time(12, 34)
a = arrow.get(datetime.combine(date.today(), t)) # <Arrow [2019-11-14T12:34:00+00:00]>
a = arrow.get(datetime.combine(date(1970, 1, 1), t)) # <Arrow [1970-01-01T12:34:00+00:00]>

You can use the strptime class method of the arrow.Arrow class and apply the appropriate formattting:
y = datetime.time()
print(arrow.Arrow.strptime(y.isoformat(), '%H:%M:%S'))
# 1900-01-01T00:00:00+00:00
However, you'll notice the date value is default, so you're probably better off parsing a datetime object instead of a time object.

Related

Get current date from datetime.datetime

I'm trying to get current date so I can pass it to the DATE field in SQL. I'm using datetime.datetime, below is my code:
from datetime import datetime
dt = datetime.strptime(datetime.today().date(), "%m/%d/%Y").date()
However, i'm getting this error:
TypeError: strptime() argument 1 must be str, not datetime.datetime
How can I fix the issue above? I'm still confused about datetime and datetime.datetime, and i want to keep using from datetime import datetime not import datetime.
How can I fix the issue above? thank you
If you see closely, the result of following statement,
>>> datetime.today().date()
datetime.date(2019, 9, 30)
>>> str(datetime.today().date())
'2019-09-30'
You'll notice that the datetime returned is - seperated and you'll have to convert it explicitly to a string value. Hence, for the above statement to work, change it to :
dt = datetime.strptime(str(datetime.today().date()), "%Y-%M-%d").date()
Then change it to whatever format you desire for using strftime (in your case >>> "%d/%m/%Y")
>>> dt.strftime("%d/%m/%Y")
'30/01/2019'
Just use datetime.strftime:
from datetime import datetime
dt = datetime.today().strftime("%m/%d/%Y")
print(dt)
Prints:
'09/30/2019'
strptime takes a string and makes a datetime object. Whereas strftime does exactly the opposite, taking a datetime object and returning a string.

How to parse time string without date and date string without time?

Is there any way to automatically parse strings with time only to datetime.time object (or something similar)? Same for datetime.date.
I've tried dateutil, arrow, moment, pandas.to_datetime.
All these parsers create timestamps with a current date.
>>> from dateutil.parser import parse
>>> parse('23:53')
datetime.datetime(2019, 1, 8, 23, 53) # datetime.time(23, 53) expected
>>> parse('2018-01-04')
datetime.datetime(2018, 1, 4, 0, 0) # datetime.date(2018, 1, 4) expected
UPD:
Thanks for the responses. Think that I should clarify the problem.
The program doesn't know what will be in the input (timestamp, date or time), and it should decide to set appropriate type. The problem is to distinguish these types.
For example, I can parse 23:53 and get a timestamp. How can I decide to extract the time from it or not?
You can use fromisoformat() from datetime.
import datetime
datetime.time.fromisoformat('23:53')
datetime.date.fromisoformat('2018-01-04')
What you basically want is for '23:53' to become a datetime.time object and for '2018-01-04' to become a datetime.date object. This cannot be achieved by using dateutil.parser.parse():
Returns a datetime.datetime object or, if the fuzzy_with_tokens option is True, returns a tuple, the first element being a datetime.datetime object, the second a tuple containing the fuzzy tokens.
From the documentation. So you'll always get a datetime.datetime object when using dateutil.parser.parse()
I would guess you need to interpret the input string yourself to define wether you're trying to parse a time or a date. When you do that, you can still use the dateutil.parser.parse() function to get the object you want:
from dateutil.parser import parse
my_time = parse('23:53')
my_time.time() # datetime.time(23, 53)
my_time.date() # datetime.date(2019, 1, 8)
Here you have an example. Just set the date attributes with replace, and select the output with strftime.
import datetime
date = datetime.datetime.now()
newdate = date.replace(hour=11, minute=59)
print(newdate.strftime('%H:%M'))
newdate2 = date.replace(year=2014, month=1, day=3)
print(newdate2.strftime('%Y-%m-%d'))
You can use either time or datetime modules, but one thing to bear in mind, is that these always create an object, that specifies a moment in time. (Also, if parsing strings, consider using the strptime function and displaying as string, strftime function respectively)
e.g.
>>> hours = time.strptime("23:59", "%H:%M")
>>> days = time.strptime("2018-01-04", "%Y-%m-%d")
>>> time.strftime("%H:%M", hours)
'23:59'
>>> time.strftime("%H:%M %Y", hours)
'23:59 1900'
Not recommended, but if you wish to separate these two object for some reason and wish to only care for a specific portion of your assignement, you can still adress the respective numbers with
>>> hours.tm_hour
23
>>> hours.tm_min
59
>>> days.tm_mon
1
>>> days.tm_mday
4
>>> days.tm_year
2018
A far better approach, in my opinion would be formatting the complete date string and using the strptime to form a complete timestamp - even if you get the time and date as separate inputs:
>>> ttime = "22:45"
>>> dday = "2018-01-04"
You can use the % formatter, or the "new" python f-Strings
>>> complete_t_string = "{} {}".format(dday, ttime)
>>> complete_t_string
'2018-01-04 22:45'
Now that we have a complete string, we can specify how it should be read and create a complete timestamp:
>>> complete_time = time.strptime(complete_t_string, "%Y-%m-%d %H:%M")
>>> complete_time
time.struct_time(tm_year=2018, tm_mon=1, tm_mday=4, tm_hour=22, tm_min=45, tm_sec=0, tm_wday=3, tm_yday=4, tm_isdst=-1)
EDIT:
Somebody will probably kill me, but if you absolutely know that you will only get two types of values, you could just do a simple try / except construct. It can probably be written more Pythonically:
try:
time.strptime(t_string, "%H:%M")
except ValueError:
time.strptime(t_string, "%Y-%m-%d")

create a datetime instance of a particular format

By default when we create a datetime instance, the format includes microseconds.
>>> from datetime import datetime
>>> datetime.now()
datetime.datetime(2017, 6, 19, 16, 13, 7, 415321)
If I don't want the microseconds part in the instance then I do this,
>>> str = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
>>> new_dt = datetime.strptime(str, '%Y-%m-%d %H:%M:%S')
So my question here is that is there any way where we can specify the format in which we want the datetime instance to be created rather than converting it to formatted string we want and then converting back to datetime instance.
A datetime object has no format. It is not created in any specific format, it is just an instance of a class. That instance has attributes, and those attributes have values.
If you need to have an instance that represents a time with the microsecond attribute set to 0, just use the datetime.replace() method to create a new instance from one with all the other attributes correct:
now = datetime.now()
now_without_ms = now.replace(microsecond=0)
However, if you wanted to format a datetime object for printing, then just format it without the microseconds component:
print(now.strftime('%Y-%m-%d %H:%M:%S'))
You don't have to use the microsecond attribute anywhere.

Python how to save datetime.strptime in datetime.time format

So I was trying to make a simple code using datetime and came across an error.
import time
from datetime import datetime
x = True
b = datetime.strptime("06:10", "%H:%M")
while x == True:
a = datetime.now().time()
print(a)
if a > b:
x = False
time.sleep(0.945)
As a result I get
TypeError: unorderable types: datetime.time() > datetime.datetime()
So I was wondering if it's possible to save a datetime.strptime in the datetime.time() format.
Thanks in advance
You tried to compare a datetime and time object, which Python won't let you compare.
If you do datetime.strptime() you get an object which holds a date and time (called datetime). But because you do not also parse the date it defaults to 01-01-1900. Now datetime.now() also gets you a datetime object but with the current date. So directly comparing datetime.now() and b won't work because the dates are different.
Now you already use the current time only by doing datetime.now().time(), so you also need to apply that to b by doing b = b.time() somewhere before the comparison.
use 'datetime.now()' insted of 'datetime.now().time()'
Compare .time() of both a and b as:
if a > b.time(): # if you want to compare only time
and not the datetime objects. Reason at the end of the answer.
datetime.now().time() is of datetime.time type:
>>> type(datetime.now().time())
<type 'datetime.time'>
whereas, datetime.strptime() and datetime.now() are of datetime.datetime type:
>>> type(datetime.strptime("06:10", "%H:%M"))
<type 'datetime.datetime'>
>>> type(datetime.now())
<type 'datetime.datetime'>
Edit based on comment from Martijn.
On creating datetime object like datetime.strptime("06:10", "%H:%M") date will be set as 1900-01-01. And definitely I dont't think you want to compare with that. You may check the date as:
>>> d = datetime.strptime("06:10", "%H:%M")
>>> d
datetime.datetime(1900, 1, 1, 6, 10)

Python: convert 'days since 1990' to datetime object

I have a time series that I have pulled from a netCDF file and I'm trying to convert them to a datetime format. The format of the time series is in 'days since 1990-01-01 00:00:00 +10' (+10 being GMT: +10)
time = nc_data.variables['time'][:]
time_idx = 0 # first timestamp
print time[time_idx]
9465.0
My desired output is a datetime object like so (also GMT +10):
"2015-12-01 00:00:00"
I have tried converting this using the time module without much success although I believe I may be using wrong (I'm still a novice in python and programming).
import time
time_datetime = time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(time[time_idx]*24*60*60))
Any advice appreciated,
Cheers!
The datetime module's timedelta is probably what you're looking for.
For example:
from datetime import date, timedelta
days = 9465 # This may work for floats in general, but using integers
# is more precise (e.g. days = int(9465.0))
start = date(1990,1,1) # This is the "days since" part
delta = timedelta(days) # Create a time delta object from the number of days
offset = start + delta # Add the specified number of days to 1990
print(offset) # >>> 2015-12-01
print(type(offset)) # >>> <class 'datetime.date'>
You can then use and/or manipulate the offset object, or convert it to a string representation however you see fit.
You can use the same format as for this date object as you do for your time_datetime:
print(offset.strftime('%Y-%m-%d %H:%M:%S'))
Output:
2015-12-01 00:00:00
Instead of using a date object, you could use a datetime object instead if, for example, you were later going to add hours/minutes/seconds/timezone offsets to it.
The code would stay the same as above with the exception of two lines:
# Here, you're importing datetime instead of date
from datetime import datetime, timedelta
# Here, you're creating a datetime object instead of a date object
start = datetime(1990,1,1) # This is the "days since" part
Note: Although you don't state it, but the other answer suggests you might be looking for timezone aware datetimes. If that's the case, dateutil is the way to go in Python 2 as the other answer suggests. In Python 3, you'd want to use the datetime module's tzinfo.
netCDF num2date is the correct function to use here:
import netCDF4
ncfile = netCDF4.Dataset('./foo.nc', 'r')
time = ncfile.variables['time'] # do not cast to numpy array yet
time_convert = netCDF4.num2date(time[:], time.units, time.calendar)
This will convert number of days since 1900-01-01 (i.e. the units of time) to python datetime objects. If time does not have a calendar attribute, you'll need to specify the calendar, or use the default of standard.
We can do this in a couple steps. First, we are going to use the dateutil library to handle our work. It will make some of this easier.
The first step is to get a datetime object from your string (1990-01-01 00:00:00 +10). We'll do that with the following code:
from datetime import datetime
from dateutil.relativedelta import relativedelta
import dateutil.parser
days_since = '1990-01-01 00:00:00 +10'
days_since_dt = dateutil.parser.parse(days_since)
Now, our days_since_dt will look like this:
datetime.datetime(1990, 1, 1, 0, 0, tzinfo=tzoffset(None, 36000))
We'll use that in our next step, of determining the new date. We'll use relativedelta in dateutils to handle this math.
new_date = days_since_dt + relativedelta(days=9465.0)
This will result in your value in new_date having a value of:
datetime.datetime(2015, 12, 1, 0, 0, tzinfo=tzoffset(None, 36000))
This method ensures that the answer you receive continues to be in GMT+10.

Categories