I have a datatime string (which comes from django/python) which looks like so:
datatime_str='2020-08-18 16:48:13.722422+00:00'
I then do, in Matlab 2018a:
fmt_dt='yyyy-MM-dd HH:mm:ss.SSSSSS+HH:mm';
datetime(datatime_str,'TimeZone','local','Format',fmt_dt);
and I get:
2020-08-18 00:00:13.722422+00:00
I am not sure what it is that I am doing wrong, but the result is obviously wrong :(
Any help would be great
Yes the +00:00 should be formatted as timezone, not hours, minute. However, you can set the display format as you would like, and this could be different from the input. The default Matlab datetime display format discards the fractional seconds (and also the timezone I think). For example:
fmt_dt_input='yyyy-MM-dd HH:mm:ss.SSSSSSxxxxx';
fmt_dt_show='yyyy-MM-dd HH:mm:ss.SSSSSS xxxxx';
datatime_str='2020-08-18 16:48:13.722422+00:00';
t = datetime(datatime_str,'InputFormat',fmt_dt_input,'TimeZone','local','Format',fmt_dt_show)
Has as output: 2020-08-18 16:48:13.722422 +00:00
EDIT: btw this info on datetime can be found here
your input string contains a UTC offset at the end, +00:00 which you parse as hours and minutes - that is why they are set to 00:00 in the result. Use e.g.
datetime('2020-08-18 16:48:13.722422+00:00', 'InputFormat', 'yyyy-MM-dd HH:mm:ss.SSSSSSZ', 'TimeZone', 'UTC')
instead (change the TimeZone parameter to whatever you need).
Related
I have this date form in python that I am writing on an api: 2022-06-01T10:36:56.000Z How can I turn this into a second? Thanks for your comments
I would like to use the seconds I have to do addition division and then go back to day/date/hour format
I can't find any content on the internet
Python cannot handle all type of iso formatted date strings. So you can use isodate library or remove .000Z from the string parsing.
You can be more clear on seconds though, is it total seconds elapsed from 1970, Jan 1 or seconds part in the date ?
k = datetime.fromisoformat("2022-06-01T10:36:56.000Z".replace(".000Z", ""))
k.timestamp()
Can someone explain to me, how to check whether a given time in "hh:mm" format falls in between a given range.
Say, given time is 10:30 A.M IST and my range is between 10:00 A.M and 11:00 A.M. So given time falls in the range.
Is there any package in python to do this in the easiest way?
Would be happy if anyone can help with this :)
The simple way is just to use datetime.time and compare in an if statement:
import datetime
hhmm = "10:30"
current_time = datetime.datetime.strptime(hhmm, "%H:%M").time()
if datetime.time(10) <= current_time <= datetime.time(11):
print("Time is between 10am and 11am")
else:
print("Time is not between 10am and 11am")
The timezone info is removed from the datetime object when .time() is called on it - if you input a literal time without a timezone, this isn't an issue, while if you do have a timezone then as long as the datetime is transformed (via .astimezone(zoneinfo.ZoneInfo('IST'))) into the timezone you want, you should just be able to compare with the literal 10am and 11am.
See also strptime() behavior, if your input format is more complicated than the above. It's possible to accommodate for AM/PM, as well as timezone.
I am using Python version 3.5. I am formatting the string 2018-07-26 12:52:18.679605-07:53 using this
datetime.datetime.strptime(2018-07-26 12:52:18.679605-07:53, "%Y-%m-%d %H:%M:%S.%f%z")
But it keeps on giving this error
time data '2018-07-26 12:52:18.679605-07:53' does not match format
'%Y-%m-%d %H:%M:%S.%f-%Z'
Please help.
why the tzinfo's delta can be 07:53?
I think it should be 08:00 or any whole hours.
Maybe you should check the time of the system which generated this time string.
Or just abandon it if you know the timezone.
Here's an array of datetime values:
array = np.array(['2016-05-01T00:00:59.3+10:00', '2016-05-01T00:02:59.4+10:00',
'2016-05-01T00:03:59.4+10:00', '2016-05-01T00:13:00.1+10:00',
'2016-05-01T00:22:00.5+10:00', '2016-05-01T00:31:01.1+10:00'],
dtype=object)
pd.to_datetime is very good at inferring datetime formats.
array = pd.to_datetime(array)
print(array)
DatetimeIndex(['2016-04-30 14:00:59.300000', '2016-04-30 14:02:59.400000',
'2016-04-30 14:03:59.400000', '2016-04-30 14:13:00.100000',
'2016-04-30 14:22:00.500000', '2016-04-30 14:31:01.100000'],
dtype='datetime64[ns]', freq=None)
How can I dynamically figure out what datetime format pd.to_datetime inferred? Something like: %Y-%m-%dT... (sorry, my datetime foo is really bad).
I don't think it's possible to do this in full generality in pandas.
As mentioned in other comments and answers, the internal function _guess_datetime_format is close to being what you ask for, but it has strict criteria for what constitutes a guessable format and so it will only work for a restricted class of datetime strings.
These criteria are set out in the _guess_datetime_format function on these lines and you can also see some examples of good and bad formats in the test_parsing script.
Some of the main points are:
year, month and day must each be present and identifiable
the year must have four digits
exactly six digits must be used if using microseconds
you can't specify a timezone
This means that it will fail to guess the format for datetime strings in the question despite them being a valid ISO 8601 format:
>>> from pandas.core.tools.datetimes import _guess_datetime_format_for_array
>>> array = np.array(['2016-05-01T00:00:59.3+10:00'])
>>> _guess_datetime_format_for_array(array)
# returns None
In this case, dropping the timezone and padding the microseconds to six digits is enough to make pandas to recognise the format:
>>> array = np.array(['2016-05-01T00:00:59.300000']) # six digits, no tz
>>> _guess_datetime_format_for_array(array)
'%Y-%m-%dT%H:%M:%S.%f'
This is probably as good as it gets.
If pd.to_datetime is not asked to infer the format of the array, or given a format string to try, it will just try and parse each string separately and hope that it is successful. Crucially, it does not need to infer a format in advance to do this.
First, pandas parses the string assuming it is (approximately) a ISO 8601 format. This begins in a call to _string_to_dts and ultimately hits the low-level parse_iso_8601_datetime function that does the hard work.
You can check if your string is able to be parsed in this way using the _test_parse_iso8601 function. For example:
from pandas._libs.tslib import _test_parse_iso8601
def is_iso8601(string):
try:
_test_parse_iso8601(string)
return True
except ValueError:
return False
The dates in the array you give are recognised as this format:
>>> is_iso8601('2016-05-01T00:00:59.3+10:00')
True
But this doesn't deliver what the question asks for and I don't see any realistic way to recover the exact format that is recognised by the parse_iso_8601_datetime function.
If parsing the string as a ISO 8601 format fails, pandas falls back to using the parse() function from the third-party dateutil library (called by parse_datetime_string). This allows a fantastic level of parsing flexibility but, again, I don't know of any good way to extract the recognised datetime format from this function.
If both of these two parsers fail, pandas either raises an error, ignores the string or defaults to NaT (depending on what the user specifies). No further attempt is made to parse the string or guess the format of the string.
DateInfer (PyDateInfer) library allows to infer dates based on the sequence of available dates:
github.com/wdm0006/dateinfer
Usage from docs:
>>> import dateinfer
>>> dateinfer.infer(['Mon Jan 13 09:52:52 MST 2014', 'Tue Jan 21 15:30:00 EST 2014'])
'%a %b %d %H:%M:%S %Z %Y'
>>>
Disclaimer: I have used and then contributed to this library
You can use _guess_datetime_format from core.tools to get the format. ie
from pandas.core.tools import datetimes as tools
tools._guess_datetime_format(pd.to_datetime(array).format()[0][:10])
Output :
'%Y-%m-%d'
To know more about this method you can see here. Hope it helps.
I have a datetime object created from which I subtract 13 days as follow:
(date.today()-timedelta(days=13)).strftime('%Y-%m-%d')
The strangeness occurs when I execute the code at 6AM and 8:30AM. At 6AM, the resulting string is returned as (if today is 2012-02-29):
2012-02-15
which is 14 days before the current! However, running the same line at 8:30AM, the resulting string is returned as:
2012-02-16
Which then correct. So far I have not been able to figure out what the difference is between the small period of time. I use timezone naive datetime objects, if that is important. I would like to know what could cause this change in the resulting string date.
Many thanks.
EDIT: (based on eumiro's suggestion below)
datetime.datetime.now() returns:
>>> datetime.datetime(2012, 2, 29, 10, 46, 20, 659862)
And the timezone is Europe/Vienna on the server and in the django application that runs the line of code.
I also tried running a similar line to the one you suggested:
(pytz.timezone(settings.TIME_ZONE).localize(datetime.now(), is_dst=True) - \
timedelta(days=13)).strftime('%Y-%m-%d')
But with the same results... which is why I think I don't think it has much to do with timezones also. But at the same time not sure where else to look.
You live somewhere in America? This is the place where the timezones are around 6-8 hours behind the UTC and that's the time of UTC midnight.
What does datetime.datetime.now() return?
If you want to get the real local time, use this (replace "America/New_York" with your timezone):
from datetime import datetime, timedelta
import pytz
now = datetime.datetime.now(pytz.timezone("America/New_York"))
dt = (now - timedelta(days=13)).strftime('%Y-%m-%d')
and it should return the same correct values from midnight until midnight.
Unfortunately DST is poorly supported in Python.
Even pytz is not perfect, but can be made to work with hacks.
You have to decide what it means to subtract 2 days from 10th, 1p.m., either 2 calendar days or 48 hours or 172800 seconds.