8

How to get the first and last second in python using the DateTime module which means 00:00:01 and 23:59:59.

I want to get the six DateTime before today.

So, for example:

today is 12/10, and I want to get

12/9 00:00:01 and 23:59:59

...

12/4 00:00:01 and 23:59:59

Thank you very much.

Ram
  • 131
  • 8
Jimmy Lin
  • 1,481
  • 6
  • 27
  • 44
  • 4
    It looks like you want us to write some code for you. While many users are willing to produce code for a coder in distress, they usually only help when the poster has already tried to solve the problem on their own. A good way to demonstrate this effort is to include the code you've written so far, example input (if there is any), the expected output, and the output you actually get (console output, stack traces, compiler errors - whatever is applicable). The more detail you provide, the more answers you are likely to receive. – Martijn Pieters Dec 01 '12 at 17:10

2 Answers2

30

Just use datetime.time.min and datetime.time.max:

>>> import datetime
>>> datetime.time.min
datetime.time(0, 0)
>>> datetime.time.max
datetime.time(23, 59, 59, 999999)

You can combine that with a datetime.date instance to get a full datetime.datetime instance:

>>> datetime.datetime.combine(datetime.date.today(), datetime.time.max)
datetime.datetime(2012, 12, 1, 23, 59, 59, 999999)

To re-use an existing datetime.datetime instance, use the .combine() method together with the .date() method on the datetime.datetime instance to create a new datetime.datetime instance:

>>> datetime.datetime.combine(datetime.datetime.now().date(), datetime.time.min)
datetime.datetime(2012, 12, 1, 0, 0)

To get a series of dates, use datetime.timedelta instances to create offsets. A series of dates relative to today is then easy:

today = datetime.date.today()
lastweek = today - datetime.timedelta(days=7)
for i in range(7):
    aday = lastweek + datetime.timedelta(days=i)
    first = datetime.datetime.combine(aday, datetime.time.min)
    last = datetime.datetime.combine(aday, datetime.time.max)
    print first, last
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • Be careful using this with timezones. `datetime.datetime.combine(utcTimezone, datetime.time.min, tzinfo=otherTimezone)` will give you the last second of the UTC timezone's day in the other timezone, not the last second of the other timezone's day in the other timezone. – Bradleo Aug 01 '22 at 04:34
  • For timezones I ended up using `my_date_time_in_timezone = my_date_time_in_utc.replace(tzinfo=timezone.utc).astimezone(tz=local_timezone)` `last_second_of_my_day = datetime.combine(my_date_time_in_timezone, time.max, tzinfo=local_timezone)` – Bradleo Aug 01 '22 at 04:46
  • @Bradleo then combine first using the source timezone before converting to the target timezone. – Martijn Pieters Aug 13 '22 at 16:09
  • @Bradleo (myself in August) setting tzinfo, which you do within replace (probably fine since its utc) and combine (much more probamatic) can [lead to times being off by a few minutes](https://stackoverflow.com/q/35462876/13815107) since timezones change slightly over time. See my answer below. – Bradleo Dec 16 '22 at 06:50
0

I had problems with the accepted answer not working with timezones (You can see my train of thought in the comments.

Here's what I came up with for use with pytz.

# utc_date_time should already be localized to UTC
# it should NOT be a naive date-time
def get_last_second_of_day_in_timezone(utc_date_time, local_timezone: str):
    local_timezone = pytz.timezone(local_timezone)
    due_date_in_timezone = utc_date_time.astimezone(local_timezone)
    last_second_of_due_day_naive = datetime.combine(due_date_in_timezone, time.max)
    last_second_of_due_day = local_timezone.localize(last_second_of_due_day_naive)
    return last_second_of_due_day

And a unit test for it

def test_get_last_second_of_day_in_timezone__previous_day_utc(self):
  utc_tz = pytz.timezone("UTC")
  ten_pm_utc = utc_tz.localize(datetime(2022, 1, 1, hour=22))

  bangladesh_timezone = "Asia/Dhaka"
  # 10pm UTC is the next day in Dhaka, so this should be the second before midnight on the 2nd
  last_second_of_jan_2_bangladesh = get_last_second_of_day_in_timezone(ten_pm_utc, bangladesh_timezone)
  self.assertEqual(last_second_of_jan_2_bangladesh.year, 2022)
  self.assertEqual(last_second_of_jan_2_bangladesh.month, 1)
  self.assertEqual(last_second_of_jan_2_bangladesh.day, 2)
  self.assertEqual(last_second_of_jan_2_bangladesh.hour, 23)
  self.assertEqual(last_second_of_jan_2_bangladesh.minute, 59)
  # This doesn't work on all machines, should find better check
  # This is because pytz.timezone(bangladesh_timezone) is the offset from the late 1800s, which is +6:02 instead of +6:00
  # self.assertEqual(last_second_of_jan_2_bangladesh.tzinfo, pytz.timezone(bangladesh_timezone))

  # Which is (23 - 6 = 17) 17:59 UTC
  last_second_of_jan_2_bangladesh_utc = last_second_of_jan_2_bangladesh.astimezone(utc_tz)
  self.assertEqual(last_second_of_jan_2_bangladesh_utc.year, 2022)
  self.assertEqual(last_second_of_jan_2_bangladesh_utc.month, 1)
  self.assertEqual(last_second_of_jan_2_bangladesh_utc.day, 2)
  self.assertEqual(last_second_of_jan_2_bangladesh_utc.hour, 17)
  self.assertEqual(last_second_of_jan_2_bangladesh_utc.minute, 59)
Bradleo
  • 167
  • 9