1

I want to save the datetime in the database as midnight for a specific user. I save the timezone on my user object. However, the database keeps saving it as midnight in UTC. Below is the code I am using.

tz_obj = pytz.timezone(user.timezone) start_date = tz_obj.normalize(date_obj.replace(day=1, hour=0, minute=0, second=0, microsecond=0)) end_date = tz_obj.normalize(date_obj.replace(day=calendar.monthrange(date_obj.year, date_obj.month)[1], hour=23, minute=59, second=59, microsecond=99999)) obj = MyObject.objects.create(start=start_date, end=end_date) 

Can someone show me how to make sure that the UTC date saved in the database is equivalent to midnight in the specified timezone.

Update Each user could have a different timezone so setting the timezone in the settings file does not solve this problem.

4
  • @DhiaTN: Each user could have different timezones. The answer you provided does not help. I did not mean to +1 your comment. Commented Dec 15, 2015 at 14:51
  • Your question was not clear enough, it's great that you updated it :) Commented Dec 15, 2015 at 14:54
  • Sorry. Thought I did with showing that the timezone is saved on the user object. Commented Dec 15, 2015 at 14:55
  • all three answers here are wrong. It is ok. The accepted answer to the duplicate has been wrong for several years too (now it is less wrong -- it works in more cases). Use my answer there if you need a correct result (according to the tz database) or a loud failure when the code can't get the result. Commented Dec 17, 2015 at 15:26

2 Answers 2

1

Note: As in comments, this approach is not correct. We need to take date object in user's timezone, as in the answer in duplicate question.

So, instead of date.today(), we would need: datetime.now(tz).date().


If I get your question right, you want to store midnight in suppose timezone +5:30, as 18:30 in UTC? If that is the case, you can do it like this:

>>> from datetime import date, time, datetime >>> naive_midnight = datetime.combine(date.today(), time()) >>> tz = pytz.timezone('Asia/Kolkata') >>> >>> # Attach local timezone to above naive datetime object >>> midnight_user_timezone = tz.localize(naive_midnight) >>> print midnigth_user_timezone 2015-12-15 00:00:00+05:30 >>> >>> # Convert to UTC >>> midnight_to_utc = midnight_user_timezone.astimezone(pytz.UTC) >>> print midnigth_to_utc 2015-12-14 18:30:00+00:00 
Sign up to request clarification or add additional context in comments.

6 Comments

This is working. The last step is not necessary since Django saves to UTC by default.
@Dan: it is wrong and it can't work unless the local timezone for your server is Asia/Kolkata. Your server's timezone should be irrelevant and it can't be equal to user.timezone in all cases (users may use different timezones).
@J.F.Sebastian I don't understand. Can you please explain what's wrong with the approach? That would be great :)
do you understand that the local date (date.today()) may be different from the date in user.timezone (datetime.now(tz).date())? Read my answer to the duplicate question
@J.F.Sebastian Oh yeah. That might create a 1 day difference. Got it. Thanks :)
|
1

Django has a function named make_aware to convert time zone naive datetime objects to time zone aware datetime objects.

aware_date_obj = make_aware(date_obj, user.timezone) 

Since the datetime object is then already linked to the correct time zone, you can simply use your .replace(day=1, hour=0, minute=0, second=0, microsecond=0) on the aware_date_obj and you will get the beginning of the year at the specified time zone.

If the datetime object is already time zone aware but not in the correct time zone, you can use the astimezone to convert it to the correct timezone:

date_obj.astimezone(user.timezone) 

Then you can again use the .replace function.

Finally, when Django stores the datetime object in the database, the time zone information will get lost. The time point will still be correct, but it will be linked to the default django time zone after the load from the database. You would then again have to use the astimezone function to link it to the correct time zone.

1 Comment

.replace(day=1,hour=0) on timezone-aware datetime object may cross a DST boundary (the result may have wrong utc offset). Read my answer to the duplicate question, to understand how to get the midnight correctly.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.