def test_trunc_time_func(self): start_datetime = microsecond_support( datetime(2015, 6, 15, 14, 30, 50, 321)) end_datetime = microsecond_support( datetime(2016, 6, 15, 14, 10, 50, 123)) if settings.USE_TZ: start_datetime = timezone.make_aware(start_datetime, is_dst=False) end_datetime = timezone.make_aware(end_datetime, is_dst=False) self.create_model(start_datetime, end_datetime) self.create_model(end_datetime, start_datetime) self.assertQuerysetEqual( DTModel.objects.annotate(extracted=TruncTime( 'start_datetime')).order_by('start_datetime'), [ (start_datetime, start_datetime.time()), (end_datetime, end_datetime.time()), ], lambda m: (m.start_datetime, m.extracted)) self.assertEqual( DTModel.objects.filter( start_datetime__time=TruncTime('start_datetime')).count(), 2) with self.assertRaisesMessage( ValueError, "Cannot truncate DateField 'start_date' to TimeField"): list(DTModel.objects.annotate(truncated=TruncTime('start_date'))) with self.assertRaisesMessage( ValueError, "Cannot truncate DateField 'start_date' to TimeField"): list( DTModel.objects.annotate(truncated=TruncTime( 'start_date', output_field=DateField())))
def get_lecture_pending(self, instance): """ Gets the lectures that are today with attendance status """ today_time = datetime.datetime.now() today = datetime.datetime.now().date() lectures = Lecture.objects.filter( course__teacher=instance, begin__date=today, begin__gt=today_time).annotate(time=TruncTime('begin')).values( 'id', 'time', 'course', code=F('course__course__code'), type=F('lecture_type')) return list(lectures)
def get_lecture_pending(self, instance): """ Gets the lectures that are today with attendance status """ today_time = datetime.datetime.now() today = datetime.datetime.now().date() lectures = Lecture.objects.all().filter(begin__date=today, begin__gt=today_time) queryset = StudentsAttendLectures.objects.filter( student=instance, lecture__in=lectures).annotate( time=TruncTime('lecture__begin')).values( 'id', 'lecture', 'present', 'time', course_id=F('lecture__course'), code=F('lecture__course__course__code')) return list(queryset)
def change_end_date_to_end_of_day(apps, schema_editor): db_alias = schema_editor.connection.alias MeteredFeatureUnitsLog = apps.get_model('silver', 'MeteredFeatureUnitsLog') if MeteredFeatureUnitsLog.objects \ .annotate(end_time=TruncTime('end_date')) \ .filter(end_time__gte=time(0, 0, 0, 1)) \ .exists(): # This check should handle a reapplication of this migration after it's already been applied # and reverted (it works when using sqlite, might not be possible to handle on other DBs) return for mful in MeteredFeatureUnitsLog.objects.using(db_alias): if mful.end_date: mful.end_date = datetime.combine( mful.end_date.date(), datetime.max.time(), tzinfo=timezone.utc, ).replace(microsecond=0) mful.save(using=db_alias)
class Match(models.Model): MATCH_START_ANNOTATION = Cast( Func( TruncDate(F('match_term__day__day')), Value(' ', output_field=CharField()), TruncTime(F('match_term__start')), output_field=CharField(), function='CONCAT', ), output_field=DateTimeField() ) objects = MatchManager() STATE_INIT = 'init' STATE_HALF_FIRST = 'half_first' STATE_HALF_PAUSE = 'pause' STATE_HALF_SECOND = 'half_second' STATE_END = 'end' STATES_CHOICES = ( 2 * (STATE_INIT,), 2 * (STATE_HALF_FIRST,), 2 * (STATE_HALF_PAUSE,), 2 * (STATE_HALF_SECOND,), 2 * (STATE_END,), ) STATES = { STATE_INIT: (STATE_HALF_FIRST,), STATE_HALF_FIRST: (STATE_HALF_PAUSE,), STATE_HALF_PAUSE: (STATE_HALF_SECOND,), STATE_HALF_SECOND: (STATE_END,), STATE_END: () } MATCH_PLAYING_STATE = (STATE_HALF_FIRST, STATE_HALF_PAUSE, STATE_HALF_SECOND) DEFAULT_STATES = (STATE_INIT, STATE_END) # by by bool(match.confirmed) HALF_LENGTH = timedelta(minutes=10) half_length = None # type: Optional[timedelta] match_term = models.ForeignKey('MatchTerm', models.PROTECT, blank=True, null=True, related_name='match_match_term') category = models.ForeignKey(Category, models.PROTECT, related_name='match_category') home_team_info = models.ForeignKey('TeamInfo', models.PROTECT, related_name='match_home_team_info') away_team_info = models.ForeignKey('TeamInfo', models.PROTECT, related_name='match_away_team_info') score_home = models.IntegerField(blank=True, null=True) score_away = models.IntegerField(blank=True, null=True) confirmed = models.DateTimeField(blank=True, null=True) confirmed_as = models.IntegerField(blank=True, null=True) online_state = models.CharField(max_length=255, choices=STATES_CHOICES, default=STATE_INIT) first_half_start = models.DateTimeField(blank=True, null=True) second_half_start = models.DateTimeField(blank=True, null=True) facebook_video_id = models.TextField(null=True, blank=True) def __str__(self): return _('{} vs. {}').format(self.home_team_info, self.away_team_info) class Meta: managed = False db_table = 'match' unique_together = (('category', 'home_team_info', 'away_team_info'),) ordering = ('match_term__day__day', 'match_term__start', 'match_term__location', 'id') def serialize(self, **kwargs): def format_color(team: "TeamInfo"): if team.dress_color_secondary: return '{t.dress_color} / {t.dress_color_secondary}'.format(t=team) return team.dress_color return dict( id=self.id, home_team_id=self.home_team_info.id, home_team_name=self.home_team_info.name, home_team_abbr=self.home_team_info.abbr or self.home_team_info.name[:4].upper(), home_team_slug=self.home_team_info.slug, home_team_color_primary=self.home_team_info.color_primary, home_team_color_secondary=self.home_team_info.color_secondary, home_team_color_text=self.home_team_info.color_text, home_team_color_name=format_color(self.home_team_info), away_team_id=self.away_team_info.id, away_team_name=self.away_team_info.name, away_team_abbr=self.away_team_info.abbr or self.away_team_info.name[:4].upper(), away_team_slug=self.away_team_info.slug, away_team_color_primary=self.away_team_info.color_primary, away_team_color_secondary=self.away_team_info.color_secondary, away_team_color_text=self.away_team_info.color_text, away_team_color_name=format_color(self.away_team_info), category_id=self.category.id, category_name=self.category.name, category_slug=self.category.slug, year_slug=self.category.year.slug, first_half_start=self.first_half_start.timestamp() if self.first_half_start else None, second_half_start=self.second_half_start.timestamp() if self.second_half_start else None, score=[self.score_home, self.score_away], confirmed=self.confirmed.timestamp() if self.confirmed else None, half_length=self.HALF_LENGTH.total_seconds() if not self.half_length else self.half_length.total_seconds(), state=self.online_state or (self.STATE_END if self.confirmed else self.STATE_INIT), facebook_video_id=self.facebook_video_id, match_term_start=self.match_term.timestamp, **kwargs ) @property def teams(self) -> Tuple["TeamInfo", "TeamInfo"]: return self.home_team_info, self.away_team_info def change_state(self, new_state: str) -> Optional["MatchEvent"]: self.refresh_from_db() if new_state not in self.STATES: logging.error('MATCH {}: Unknown state {} to set.'.format(self.id, new_state)) return if new_state not in self.STATES.get(self.online_state, self.DEFAULT_STATES[bool(self.confirmed)]): # logging.error('Cannot go from {} to {}.'.format(self.online_state, new_state)) return logging.info('MATCH {}: Match state change from {} to {}.'.format(self.id, self.online_state, new_state)) old_state = self.online_state self.online_state = new_state self.save(update_fields=('online_state',)) event = MatchEvent(match=self) if not old_state or old_state == self.STATE_INIT: event.type = MatchEvent.TYPE_START event.half_index = event.time_offset = 0 self.score_away = self.score_home = 0 self.save(update_fields=('score_home', 'score_away',)) elif old_state == self.STATE_HALF_FIRST: event.type = MatchEvent.TYPE_END event.half_index = 0 event.time_offset = Match.HALF_LENGTH.total_seconds() elif old_state == self.STATE_HALF_PAUSE: event.type = MatchEvent.TYPE_START event.half_index = 1 event.time_offset = 0 elif old_state == self.STATE_HALF_SECOND: event.type = MatchEvent.TYPE_END event.half_index = 1 event.time_offset = Match.HALF_LENGTH.total_seconds() else: raise RuntimeError('Never happen: {} -> {}.'.format(old_state, new_state)) event.save() return event def on_timer_end(self) -> Optional['MatchEvent']: self.refresh_from_db() event = None if self.online_state == Match.STATE_HALF_FIRST: event = self.change_state(Match.STATE_HALF_PAUSE) elif self.online_state == Match.STATE_HALF_SECOND: event = self.change_state(Match.STATE_END) return event