1

I have a test in Django 1.8.5, which passes. Here is is

def test_user_returns_from_vacation_correctly_increments_review_timestamps(self):
        self.user.profile.on_vacation = True

        now = timezone.now()
        an_hour_ago = now - timedelta(hours=1)
        two_hours_ago = now - timedelta(hours=2)

        self.user.profile.vacation_date = an_hour_ago
        self.user.profile.save()
        self.review.last_studied = two_hours_ago
        self.review.save()
        previously_studied = self.review.last_studied

        user_returns_from_vacation(self.user)
        rev = UserSpecific.objects.get(id=self.review.id) #<---This is the line causing the error!
        print(rev)
        self.assertNotEqual(rev.last_studied, previously_studied)
        self.assertAlmostEqual(rev.last_studied, an_hour_ago, delta=timedelta(seconds=1))

However upon upgrading to Django 1.9 this test causes this error:

Error
Traceback (most recent call last):
/pytz/tzinfo.py", line 304, in localize
etc etc
    raise ValueError('Not naive datetime (tzinfo is already set)')
ValueError: Not naive datetime (tzinfo is already set)

Here is the related user_returns_from_vacation code:

def user_returns_from_vacation(user):
    """
    Called when a user disables vacation mode. A one-time pass through their reviews in order to correct their last_studied_date, and quickly run an SRS run to determine which reviews currently need to be looked at.
    """
    logger.info("{} has returned from vacation!".format(user.username))
    vacation_date = user.profile.vacation_date
    if vacation_date:
        users_reviews = UserSpecific.objects.filter(user=user)
        elapsed_vacation_time = timezone.now() - vacation_date
        logger.info("User {} has been gone for timedelta: {}".format(user.username, str(elapsed_vacation_time)))
        updated_count = users_reviews.update(last_studied=F('last_studied') + elapsed_vacation_time)
        users_reviews.update(next_review_date=F('next_review_date') + elapsed_vacation_time)
        logger.info("brought {} reviews out of hibernation for {}".format(updated_count, user.username))

    user.profile.vacation_date = None
    user.profile.on_vacation = False
    user.profile.save()

UPDATE: If I remove the F() expressions, and replace them with a for loop, this error disappears. Like so:

    for rev in users_reviews:
        lst = rev.last_studied
        nsd = rev.next_review_date
        rev.last_studied = lst + elapsed_vacation_time
        rev.next_review_date = nsd + elapsed_vacation_time
        rev.save()

I noticed in the release notes for 1.9 that they had added a TIME_ZONE attribute for timezone-naive databases (like SQLite, which is what I run my tests with). I've tried adding my timezone to the DB config, but the issue persists. Any ideas? Here are my timezone-related settings in settings.py

MY_TIME_ZONE = 'America/New_York'
TIME_ZONE = MY_TIME_ZONE
DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.sqlite3',
            'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
            'TIME_ZONE': MY_TIME_ZONE
        }
Tadgh
  • 1,999
  • 10
  • 23
  • Might Want to look at this - https://docs.djangoproject.com/en/1.9/topics/i18n/timezones/ – Manish Gupta May 23 '16 at 17:22
  • I've read this, and I've read the 1.8 version as well. Since there is no difference, this does not explain why my test is failing in one version, and not the other. – Tadgh May 23 '16 at 17:37

1 Answers1

0

Eventually after hassling the core developers, I found that this is indeed a bug, specifically when using SQLite. It is documented here, but is still unfixed:

https://code.djangoproject.com/ticket/27544

Tadgh
  • 1,999
  • 10
  • 23