python date unix 1 day is lost - python

I have an error in python, when extracting one day. I'm converting to unix and extracting one day, yet the 11th of march - is always missing, no matter how big the dataset. Could anyone tell me what might be the error ?
from time import localtime, mktime, strptime, strftime
day = str(20180313)
one_day = 86400
for i in range(1,5):
print(day)
previous_day_unix = int( mktime( strptime( day, "%Y%m%d")))-one_day
day = strftime("%Y%m%d", localtime(int(previous_day_unix)))
print(day)

Daylight saving time 2018 began at 2:00 AM on March 11, 2018. Thus this day wasn't 86400 seconds.
As you can see subtracting 86400 seconds is not a good way to compute differences in days. In general, all date/time "math" operations are a little more complicated than simple multiplies and adds due to things like timezones, daylight savings, and leap years.
A better way is to use a library, such as the datetime, which handles all of these things for you:
from datetime import datetime, timedelta
day = str(20180313)
for i in range(1, 5):
print(day)
previous_day = (datetime.strptime(day, "%Y%m%d") - timedelta(days=1))
day = previous_day.strftime("%Y%m%d")
#20180313
#20180312
#20180311
#20180310

Related

Python: Comparing two dates

I would like to know how many days are passed from a x ago to today
I wrote this:
from datetime import datetime
timestamp = 1629195530 # A month ago
before = datetime.fromtimestamp(timestamp)
daysBefore = before.strftime("%d")
now = datetime.now()
today = now.strftime("%d")
print(f"daysBefore {daysBefore} - today {today}")
daysPassed = int(today) - int(daysBefore)
But so it seems, daysBefore is returning the days of the month, I can't get my head around this :(
Exact format with date time hour minute accuracy
from datetime import datetime
timestamp = 1629195530 # A month ago
before = datetime.fromtimestamp(timestamp)
now = datetime.now()
print(now - before))
print(f"daysBefore {daysBefore} - today {today}")
The reason this doesn't work is that it gives the day of the month. For example 17th of July and 17th of August will give a difference of zero days.
Therefore the recommend method is as #abdul Niyas P M says, use the whole date.time format to subtract two dates and afterwards extract the days.
Your issue is due to this: strftime("%d")
You are converting you date to a string and then to an int to make the difference. You can just use the datetime to do this for you:
timestamp = 1629195530 # A month ago
before = datetime.fromtimestamp(timestamp)
now = datetime.now()
print(f"daysBefore {before} - today {now}")
daysPassed = now - before
print(daysPassed.days)

How do I calculate the actual number of hours in a day according to a local calendar in Python?

I'd like to write a small function that can calculate the number of hours in any given day, for any time zone. The obvious approach was to count the hours between the first instant of the day and the next day. Unfortunately, whatever day I choose, this approach always says that a day is 24 hours long.
In the UK, the clocks are advanced at 1am in March by 1 hour. That means the 28th March 2021 should have 23 hours. The time-range from 1am to 2am will not have existed that day.
Likewise, on the 31st October 2021 the clock is pushed back at 1am, so that day will have 25 hours. The time-range midnight to 1am will have occurred twice in that day.
import datetime
import pytz
# When do the clocks change?
# https://www.gov.uk/when-do-the-clocks-change
day0=datetime.datetime(2021,3,28, tzinfo=pytz.timezone("Europe/London"))
day1=datetime.datetime(2021,3,29, tzinfo=pytz.timezone("Europe/London"))
delta = day1-day0
print(delta)
hours = delta / datetime.timedelta(hours=1)
print(hours)
This script gives output that seems incorrect:
1 day, 0:00:00
24.0
Is there a simpler way to get the number of hours in a particular day, that gives the right answer?
Ideally this should be able to account for daylight savings, leap-years and even leap seconds.
Part of the issue is "using the tzinfo argument of the standard datetime constructors ‘’does not work’’ with pytz for many timezones."
So we can work around that by using timezone.localize() with a local naive time (no tz):
London = pytz.timezone("Europe/London")
day0 = London.localize(datetime.datetime(2021,3,28))
day1 = London.localize(datetime.datetime(2021,3,29))
(day1 - day0).total_seconds() / 60 / 60 # in hours
# 23.0
And for 31st October:
day0 = London.localize(datetime.datetime(2021, 10, 31))
day1 = London.localize(datetime.datetime(2021, 11, 1))
(day1 - day0).total_seconds() / 60 / 60
# 25.0

Get next midnight date and time using Python time library only

I have a timestamp generated from time.time().
Example: 1597316030
Converting to date and time this gives "Thursday, August 13, 2020 10:53:50 AM GMT+00:00".
Is it possible to get the timestamp that would correspond to "Thursday, August 14, 2020 12:00:00 AM GMT+00:00" (next midnight, or any other date and time), using only time library (without date or datetime, for example)?
Thanks!
using only time library (without date or datetime, for example)?
It is possible without any library and quite simple after you realize that: 0 is start of epoch is midnight 1 Jan 1970 and every 24 hour is 86400 second, therefore any midnight will be multiply of 86400, thus you just need to find smallest multiply of 86400 greater than your timestamp, which can be done following way:
t = 1597316030
t2 = ((t//86400)+1)*86400
print(t2)
Output:
1597363200
Keep in mind that this solution totally ignore existence of timezones.

Convert hours from January 1st midnight to actual date

I'm working with some telemetry that uses timestamps measured in hours since January 1st at midnight of the current year.
So I get value 1 at time 8668.12034
I'd like to convert it to a more useful date format and of course I've been doing so with hardcoded math dividing into days, remainder hours, minutes, etc accounting for leap years... and it works but I'm sure there's a simple way using the datetime library or something right?
I'm thinking timedelta is the way to go since it's giving me a delta since the beginning of the year but does that account for leap years?
Curious how others would approach this issue, thanks for any advice.
# import packages we need
import datetime
From elapsed hours to datetime.datetime object
You can for example do:
hours_elapsed = 1000
your_date = datetime.datetime(2020,1,1,0,0)+datetime.timedelta(hours=hours_elapsed)
(Of course change hours_elapsed to whatever hours elapsed in your case.)
your_date will be: datetime.datetime(2020, 2, 11, 16, 0)
Yes, timedelta does know about leap years.
Further processing
If want to process this further, can do, using getattr():
timeunits = ['year', 'month', 'day', 'hour', 'minute', 'second']
[getattr(your_date,timeunit) for timeunit in timeunits]
Resulting in:
[2020, 2, 11, 16, 0, 0]

dateutil.relativedelta - How to get duration in days?

I wish to get the total duration of a relativedelta in terms of days.
Expected:
dateutil.timedelta(1 month, 24 days) -> dateutil.timedelta(55 days)
What I tried:
dateutil.timedelta(1 month, 24 days).days -> 24 (WRONG)
Is there a simple way to do this? Thanks!
This one bothered me as well. There isn't a very clean way to get the span of time in a particular unit. This is partly because of the date-range dependency on units.
relativedelta() takes an argument for months. But when you think about how long a month is, the answer is "it depends". With that said, it's technically impossible to convert a relativedelta() directly to days, without knowing which days the delta lands on.
Here is what I ended up doing.
from datetime import datetime, timedelta
from dateutil.relativedelta import relativedelta
rd = relativedelta(years=3, months=7, days=19)
# I use 'now', but you may want to adjust your start and end range to a specific set of dates.
now = datetime.now()
# calculate the date difference from the relativedelta span
then = now - rd
# unlike normal timedelta 'then' is returned as a datetime
# subtracting two dates will give you a timedelta which contains the value you're looking for
diff = now - then
print diff.days
Simple date diff does it actually.
>>> from datetime import datetime
>>> (datetime(2017, 12, 1) - datetime(2018, 1, 1)).days
-31
To get positive number You can swap dates or use abs:
>>> abs((datetime(2017, 12, 1) - datetime(2018, 1, 1)).days)
31
In many situations you have a much restricted relativedelta, in my case, my relativedelta had only relative fields set (years, months, weeks, and days) and no other field. You may be able to get away with the simple method.
This is definitely off by few days, but it may be all you need
(365 * duration.years) + (30 * duration.months) + (duration.days)

Categories

Resources