Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cast bill action dates to date objects, not date time objects #272

Merged
merged 7 commits into from
Sep 15, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions councilmatic_core/feeds.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from django.conf import settings

from .models import Person, Bill, Organization, Event
from .utils import to_datetime


class CouncilmaticFacetedSearchFeed(Feed):
Expand Down Expand Up @@ -71,7 +72,7 @@ def item_link(self, bill):
return reverse('bill_detail', args=(bill.slug,))

def item_pubdate(self, bill):
return bill.last_action_date
return to_datetime(bill.last_action_date)

def description(self, obj):
return "Bills returned from search"
Expand Down Expand Up @@ -114,7 +115,7 @@ def item_link(self, bill):
return reverse('bill_detail', args=(bill.slug,))

def item_pubdate(self, bill):
return bill.last_action_date
return to_datetime(bill.last_action_date)

def description(self, obj):
return "Recent sponsored bills from " + obj.name + "."
Expand Down Expand Up @@ -187,7 +188,7 @@ def item_link(self, action):
return reverse('bill_detail', args=(action.bill.slug,))

def item_pubdate(self, action):
return action.date_dt
return to_datetime(action.date_dt)

def description(self, obj):
return "Actions for committee %s" % obj.name
Expand Down Expand Up @@ -223,7 +224,7 @@ def item_link(self, action):
return reverse('bill_detail', args=(action.bill.slug,))

def item_pubdate(self, action):
return action.date_dt
return to_datetime(action.date_dt)

def description(self, obj):
return "Actions for bill %s" % obj.friendly_name
Expand Down
4 changes: 1 addition & 3 deletions councilmatic_core/haystack_indexes.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,5 @@ def get_updated_field(self):
return 'updated_at'

def prepare_last_action_date(self, obj):
# Solr seems to be fussy about the time format, and we do not need the time, just the date stamp.
# https://lucene.apache.org/solr/guide/7_5/working-with-dates.html#date-formatting
if obj.last_action_date:
return obj.last_action_date.date()
return obj.last_action_date
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 2.2.16 on 2020-09-15 15:27

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('councilmatic_core', '0051_bill_last_action_date'),
]

operations = [
migrations.AlterField(
model_name='bill',
name='last_action_date',
field=models.DateField(blank=True, null=True),
),
]
28 changes: 18 additions & 10 deletions councilmatic_core/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,21 +24,29 @@
class CastToDateTimeMixin:

@classmethod
def cast_to_datetime(cls, field):
def _cast(cls, field, field_type):
"""
Cast a given field from a CharField to a DateTimeField, converting empty
strings to NULL in the process. Useful for CharFields that store timestamps
as strings.
Cast a given field from a CharField to a DateField or a DateTimeField,
converting empty strings to NULL in the process. Useful for CharFields
that store timestamps as strings.
"""
return Cast(
Case(
When(**{field: '', 'then': None}),
default=field,
output_field=models.CharField()
),
models.DateTimeField()
field_type
)

@classmethod
def cast_to_date(cls, field):
return cls._cast(field, models.DateField())

@classmethod
def cast_to_datetime(cls, field):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we need this path around?

Copy link
Member Author

@hancush hancush Sep 15, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question! We're still using it for event start dates, as well as membership start and end dates. We'll eventually transition membership start/end dates to date objects, but events actually come with a date time string, so we'll still use it there.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ty.

return cls._cast(field, models.DateTimeField())


class Person(opencivicdata.core.models.Person):

Expand Down Expand Up @@ -90,7 +98,7 @@ def sponsorship_sort(sponsorship):
'''
Sponsorships of bills without recent action dates should appear last.
'''
return sponsorship.bill.last_action_date or datetime.datetime(datetime.MINYEAR, 1, 1)
return sponsorship.bill.last_action_date or datetime.date(datetime.MINYEAR, 1, 1)

return sorted((s for s in primary_sponsorships), key=sponsorship_sort, reverse=True)

Expand Down Expand Up @@ -388,7 +396,7 @@ class Bill(opencivicdata.legislative.models.Bill):

slug = models.SlugField(unique=True)
restrict_view = models.BooleanField(default=False)
last_action_date = models.DateTimeField(blank=True, null=True)
last_action_date = models.DateField(blank=True, null=True)

def delete(self, **kwargs):
kwargs['keep_parents'] = kwargs.get('keep_parents', True)
Expand Down Expand Up @@ -567,7 +575,7 @@ def bills_since(cls, date_cutoff):
"""
grabs all bills that have had activity since a given date
"""
return cls.objects.filter(last_action_date_dt__gte=date_cutoff)
return cls.objects.filter(last_action_date__gte=date_cutoff)

@classmethod
def new_bills_since(cls, date_cutoff):
Expand Down Expand Up @@ -616,7 +624,7 @@ def get_last_action_date(self):
return None

else:
return last_agenda.start_time
return last_agenda.start_time.date()


class BillSponsorship(opencivicdata.legislative.models.BillSponsorship):
Expand All @@ -631,7 +639,7 @@ class Meta:
class BillActionManager(CastToDateTimeMixin, models.Manager):
def get_queryset(self):
return super().get_queryset().annotate(
date_dt=self.cast_to_datetime('date')
date_dt=self.cast_to_date('date')
)


Expand Down
14 changes: 14 additions & 0 deletions councilmatic_core/utils.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import datetime
import pytz

from django.conf import settings
from haystack.utils.highlighting import Highlighter


Expand All @@ -23,3 +27,13 @@ def make_query_words(self, query):
query_words = set([word.lower() for word in query.split() if not word.startswith("-")])

return query_words


def to_datetime(date, local=False):
dt = datetime.datetime(date.year, date.month, date.day)

if local:
return pytz.timezone(settings.TIME_ZONE).localize(dt)

else:
return dt