work on timezone bug -- still need run checks
This commit is contained in:
		@ -84,8 +84,7 @@ class Monitor:
 | 
			
		||||
        if not current_sound or not current_source:
 | 
			
		||||
            return
 | 
			
		||||
 | 
			
		||||
        log = Log.objects.get_for(model = Sound) \
 | 
			
		||||
                         .filter(station = self.station) \
 | 
			
		||||
        log = Log.objects.get_for(self.station, model = Sound) \
 | 
			
		||||
                         .order_by('date').last()
 | 
			
		||||
 | 
			
		||||
        # only streamed
 | 
			
		||||
@ -113,7 +112,7 @@ class Monitor:
 | 
			
		||||
        Log tracks for the given sound (for streamed programs); Called by
 | 
			
		||||
        self.trace
 | 
			
		||||
        """
 | 
			
		||||
        logs = Log.objects.get_for(model = Track) \
 | 
			
		||||
        logs = Log.objects.get_for(self.station, model = Track) \
 | 
			
		||||
                          .filter(pk__gt = log.pk)
 | 
			
		||||
        logs = [ log.related_id for log in logs ]
 | 
			
		||||
 | 
			
		||||
@ -160,11 +159,11 @@ class Monitor:
 | 
			
		||||
        if not self.cancel_timeout:
 | 
			
		||||
            return
 | 
			
		||||
 | 
			
		||||
        diffs = Diffusions.objects.get_at().filter(
 | 
			
		||||
        diffs = Diffusions.objects.at(self.station).filter(
 | 
			
		||||
            type = Diffusion.Type.normal,
 | 
			
		||||
            sound__type = Sound.Type.archive,
 | 
			
		||||
        )
 | 
			
		||||
        logs = station.get_played(models = Diffusion)
 | 
			
		||||
        logs = station.played(models = Diffusion)
 | 
			
		||||
 | 
			
		||||
        date = tz.now() - datetime.timedelta(seconds = self.cancel_timeout)
 | 
			
		||||
        for diff in diffs:
 | 
			
		||||
@ -188,14 +187,14 @@ class Monitor:
 | 
			
		||||
        station = self.station
 | 
			
		||||
        now = tz.now()
 | 
			
		||||
 | 
			
		||||
        diff_log = station.get_played(models = Diffusion) \
 | 
			
		||||
        diff_log = station.played(models = Diffusion) \
 | 
			
		||||
                          .order_by('date').last()
 | 
			
		||||
        if not diff_log or \
 | 
			
		||||
                not diff_log.related.is_date_in_range(now):
 | 
			
		||||
            return None, []
 | 
			
		||||
 | 
			
		||||
        # sound has switched? assume it has been (forced to) stopped
 | 
			
		||||
        sounds = station.get_played(models = Sound) \
 | 
			
		||||
        sounds = station.played(models = Sound) \
 | 
			
		||||
                        .filter(date__gte = diff_log.date) \
 | 
			
		||||
                        .order_by('date')
 | 
			
		||||
 | 
			
		||||
@ -228,7 +227,7 @@ class Monitor:
 | 
			
		||||
        now = tz.now()
 | 
			
		||||
 | 
			
		||||
        args = {'start__gt': diff.date } if diff else {}
 | 
			
		||||
        diff = Diffusion.objects.get_at(now).filter(
 | 
			
		||||
        diff = Diffusion.objects.at(station, now).filter(
 | 
			
		||||
            type = Diffusion.Type.normal,
 | 
			
		||||
            sound__type = Sound.Type.archive,
 | 
			
		||||
            **args
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										195
									
								
								aircox/models.py
									
									
									
									
									
								
							
							
						
						
									
										195
									
								
								aircox/models.py
									
									
									
									
									
								
							@ -27,7 +27,7 @@ logger = logging.getLogger('aircox.core')
 | 
			
		||||
# Abstracts
 | 
			
		||||
#
 | 
			
		||||
class RelatedManager(models.Manager):
 | 
			
		||||
    def get_for(self, object = None, model = None):
 | 
			
		||||
    def get_for(self, object = None, model = None, qs = None):
 | 
			
		||||
        """
 | 
			
		||||
        Return a queryset that filter on the given object or model(s)
 | 
			
		||||
 | 
			
		||||
@ -37,13 +37,15 @@ class RelatedManager(models.Manager):
 | 
			
		||||
        if not model and object:
 | 
			
		||||
            model = type(object)
 | 
			
		||||
 | 
			
		||||
        qs = qs or self
 | 
			
		||||
        if hasattr(model, '__iter__'):
 | 
			
		||||
            model = [ ContentType.objects.get_for_model(m).id
 | 
			
		||||
                        for m in model ]
 | 
			
		||||
            qs = self.filter(related_type__pk__in = model)
 | 
			
		||||
            qs = qs.filter(related_type__pk__in = model)
 | 
			
		||||
        else:
 | 
			
		||||
            model = ContentType.objects.get_for_model(model)
 | 
			
		||||
            qs = self.filter(related_type__pk = model.id)
 | 
			
		||||
            qs = qs.filter(related_type__pk = model.id)
 | 
			
		||||
 | 
			
		||||
        if object:
 | 
			
		||||
            qs = qs.filter(related_id = object.pk)
 | 
			
		||||
        return qs
 | 
			
		||||
@ -224,23 +226,11 @@ class Station(Nameable):
 | 
			
		||||
        self.__prepare()
 | 
			
		||||
        return self.__streamer
 | 
			
		||||
 | 
			
		||||
    def get_played(self, models, archives = True):
 | 
			
		||||
    def played(self, models, archives = True):
 | 
			
		||||
        """
 | 
			
		||||
        Return a queryset with log of played elements on this station,
 | 
			
		||||
        of the given models, ordered by date ascending.
 | 
			
		||||
 | 
			
		||||
        * models: a model or a list of models
 | 
			
		||||
        * archives: if false, exclude log of diffusion's archives from
 | 
			
		||||
            the queryset;
 | 
			
		||||
        Call Log.objects.played for this station
 | 
			
		||||
        """
 | 
			
		||||
        qs = Log.objects.get_for(model = models) \
 | 
			
		||||
                .filter(station = self, type = Log.Type.play)
 | 
			
		||||
        if not archives and self.dealer:
 | 
			
		||||
            qs = qs.exclude(
 | 
			
		||||
                source = self.dealer.id,
 | 
			
		||||
                related_type = ContentType.objects.get_for_model(Sound)
 | 
			
		||||
            )
 | 
			
		||||
        return qs.order_by('date')
 | 
			
		||||
        return Log.objects.played(self, models, archives)
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def __mix_logs_and_diff(diffs, logs, count = 0):
 | 
			
		||||
@ -319,16 +309,17 @@ class Station(Nameable):
 | 
			
		||||
        if not date and not count:
 | 
			
		||||
            raise ValueError('at least one argument must be set')
 | 
			
		||||
 | 
			
		||||
        # FIXME can be a potential source of bug
 | 
			
		||||
        if date and date > datetime.date.today():
 | 
			
		||||
            return []
 | 
			
		||||
 | 
			
		||||
        logs = Log.objects.get_for(model = Track) \
 | 
			
		||||
                  .filter(station = self)
 | 
			
		||||
        if date:
 | 
			
		||||
            logs = logs.filter(date__contains = date)
 | 
			
		||||
            diffs = Diffusion.objects.get_at(date)
 | 
			
		||||
            logs = Log.objects.at_for(self, date, model = Track)
 | 
			
		||||
            diffs = Diffusion.objects.at(self, date)
 | 
			
		||||
        else:
 | 
			
		||||
            logs = Log.objects.get_for(self, model = Track)
 | 
			
		||||
            diffs = Diffusion.objects
 | 
			
		||||
        logs = logs.filter(station = self)
 | 
			
		||||
 | 
			
		||||
        diffs = diffs.filter(program__station = self) \
 | 
			
		||||
                     .filter(type = Diffusion.Type.normal) \
 | 
			
		||||
@ -345,6 +336,11 @@ class Station(Nameable):
 | 
			
		||||
        super().save(*args, **kwargs)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ProgramManager(models.Manager):
 | 
			
		||||
    def station(self, station, qs = None):
 | 
			
		||||
        qs = qs or self
 | 
			
		||||
        return qs.filter(station = station)
 | 
			
		||||
 | 
			
		||||
class Program(Nameable):
 | 
			
		||||
    """
 | 
			
		||||
    A Program can either be a Streamed or a Scheduled program.
 | 
			
		||||
@ -373,6 +369,8 @@ class Program(Nameable):
 | 
			
		||||
        help_text = _('update later diffusions according to schedule changes')
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    objects = ProgramManager()
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def path(self):
 | 
			
		||||
        """
 | 
			
		||||
@ -586,7 +584,7 @@ class Schedule(models.Model):
 | 
			
		||||
 | 
			
		||||
        if self.frequency == Schedule.Frequency.one_on_two:
 | 
			
		||||
            # cf notes in date_of_month
 | 
			
		||||
            diff = utils.as_date(date, False) - utils.as_date(self.date, False)
 | 
			
		||||
            diff = utils.cast_date(date, False) - utils.cast_date(self.date, False)
 | 
			
		||||
            return not (diff.days % 14)
 | 
			
		||||
 | 
			
		||||
        first_of_month = date.replace(day = 1)
 | 
			
		||||
@ -601,14 +599,16 @@ class Schedule(models.Model):
 | 
			
		||||
    def normalize(self, date):
 | 
			
		||||
        """
 | 
			
		||||
        Set the time of a datetime to the schedule's one
 | 
			
		||||
        Ensure timezone awareness.
 | 
			
		||||
        """
 | 
			
		||||
        date = date.replace(hour = self.date.hour, minute = self.date.minute,
 | 
			
		||||
                            second = 0)
 | 
			
		||||
        date = tz.datetime(date.year, date.month, date.day,
 | 
			
		||||
                           self.date.hour, self.date.minute, 0, 0)
 | 
			
		||||
        return date if tz.is_aware(date) else tz.make_aware(date)
 | 
			
		||||
 | 
			
		||||
    def dates_of_month(self, date = None):
 | 
			
		||||
        """
 | 
			
		||||
        Return a list with all matching dates of date.month (=today)
 | 
			
		||||
        Ensure timezone awareness.
 | 
			
		||||
        """
 | 
			
		||||
        if self.frequency == Schedule.Frequency.ponctual:
 | 
			
		||||
            return []
 | 
			
		||||
@ -622,10 +622,10 @@ class Schedule(models.Model):
 | 
			
		||||
 | 
			
		||||
            # end of month before the wanted weekday: move one week back
 | 
			
		||||
            if date.weekday() < self.date.weekday():
 | 
			
		||||
                date -= datetime.timedelta(days = 7)
 | 
			
		||||
                date -= tz.timedelta(days = 7)
 | 
			
		||||
 | 
			
		||||
            delta = self.date.weekday() - date.weekday()
 | 
			
		||||
            date += datetime.timedelta(days = delta)
 | 
			
		||||
            date += tz.timedelta(days = delta)
 | 
			
		||||
            return [self.normalize(date)]
 | 
			
		||||
 | 
			
		||||
        # move to the first day of the month that matches the schedule's weekday
 | 
			
		||||
@ -639,7 +639,7 @@ class Schedule(models.Model):
 | 
			
		||||
        dates = []
 | 
			
		||||
        if freq == Schedule.Frequency.one_on_two:
 | 
			
		||||
            # check date base on a diff of dates base on a 14 days delta
 | 
			
		||||
            diff = utils.as_date(date, False) - utils.as_date(self.date, False)
 | 
			
		||||
            diff = utils.cast_date(date, False) - utils.cast_date(self.date, False)
 | 
			
		||||
            if diff.days % 14:
 | 
			
		||||
                date += tz.timedelta(days = 7)
 | 
			
		||||
 | 
			
		||||
@ -716,51 +716,81 @@ class Schedule(models.Model):
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DiffusionManager(models.Manager):
 | 
			
		||||
    def get_at(self, date = None, next = False):
 | 
			
		||||
    def station(self, station, qs = None):
 | 
			
		||||
        qs = qs or self
 | 
			
		||||
        return qs.filter(program__station = station)
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def __in_range(field, range, field_ = None, reversed = False):
 | 
			
		||||
        """
 | 
			
		||||
        Return a queryset of diffusions that have the given date
 | 
			
		||||
        in their range.
 | 
			
		||||
 | 
			
		||||
        If date is a datetime.date object, check only against the
 | 
			
		||||
        date.
 | 
			
		||||
        Return a kwargs to catch diffusions based on the given field name
 | 
			
		||||
        and datetime range.
 | 
			
		||||
        """
 | 
			
		||||
        date = utils.date_or_default(date)
 | 
			
		||||
        if not issubclass(type(date), datetime.datetime):
 | 
			
		||||
            return self.filter(
 | 
			
		||||
                models.Q(start__contains = date) | \
 | 
			
		||||
                models.Q(end__contains = date)
 | 
			
		||||
            )
 | 
			
		||||
        if reversed:
 | 
			
		||||
            return { field + "__lte": range[1],
 | 
			
		||||
                     (field_ or field) + "__gte": range[0] }
 | 
			
		||||
 | 
			
		||||
        return { field + "__gte" : range[0],
 | 
			
		||||
                 (field_ or field) + "__lte" : range[1] }
 | 
			
		||||
 | 
			
		||||
        if not date.is_aware():
 | 
			
		||||
            date = make_aware(date)
 | 
			
		||||
    def at(self, station, date = None, next = False, qs = None):
 | 
			
		||||
        """
 | 
			
		||||
        Return diffusions occuring at the given date, ordered by +start
 | 
			
		||||
 | 
			
		||||
        if not next:
 | 
			
		||||
            return self.filter(start__lte = date, end__gte = date) \
 | 
			
		||||
                       .order_by('start')
 | 
			
		||||
        If date is a datetime instance, get diffusions that occurs at
 | 
			
		||||
        the given moment. If date is not a datetime object, it uses
 | 
			
		||||
        it as a date, and get diffusions that occurs this day.
 | 
			
		||||
 | 
			
		||||
        return self.filter(
 | 
			
		||||
            models.Q(start__lte = date, end__gte = date) |
 | 
			
		||||
            models.Q(start__gte = date),
 | 
			
		||||
        ).order_by('start')
 | 
			
		||||
        When date is None, uses tz.now().
 | 
			
		||||
 | 
			
		||||
    def get_after(self, date = None):
 | 
			
		||||
        When next is true, include diffusions that also occur after
 | 
			
		||||
        the given moment.
 | 
			
		||||
        """
 | 
			
		||||
        # note: we work with localtime
 | 
			
		||||
        date = utils.date_or_default(date, keep_type = True)
 | 
			
		||||
 | 
			
		||||
        qs = qs or self
 | 
			
		||||
        filters = None
 | 
			
		||||
        if isinstance(date, datetime.datetime):
 | 
			
		||||
            # use datetime: we want diffusion that occurs around this
 | 
			
		||||
            # range
 | 
			
		||||
            range = date, date
 | 
			
		||||
            filters = self.__in_range('start', range, 'end', True)
 | 
			
		||||
            if next:
 | 
			
		||||
                qs = qs.filter(
 | 
			
		||||
                    models.Q(date__gte = date) | models.Q(**filters)
 | 
			
		||||
                )
 | 
			
		||||
            else:
 | 
			
		||||
                qs = qs.filter(**filters)
 | 
			
		||||
        else:
 | 
			
		||||
            # use date: we want diffusions that occurs this day
 | 
			
		||||
            range = utils.date_range(date)
 | 
			
		||||
            filters = models.Q(**self.__in_range('start', range)) | \
 | 
			
		||||
                     models.Q(**self.__in_range('end', range))
 | 
			
		||||
            if next:
 | 
			
		||||
                # include also diffusions of the next day
 | 
			
		||||
                filters |= models.Q(start__gte = range[0])
 | 
			
		||||
            qs = qs.filter(filters)
 | 
			
		||||
        return self.station(station, qs).order_by('start').distinct()
 | 
			
		||||
 | 
			
		||||
    def after(self, station, date = None, qs = None):
 | 
			
		||||
        """
 | 
			
		||||
        Return a queryset of diffusions that happen after the given
 | 
			
		||||
        date.
 | 
			
		||||
        """
 | 
			
		||||
        date = utils.date_or_default(date)
 | 
			
		||||
        return self.filter(
 | 
			
		||||
        return self.station(station, qs).filter(
 | 
			
		||||
            start__gte = date,
 | 
			
		||||
        ).order_by('start')
 | 
			
		||||
 | 
			
		||||
    def get_before(self, date):
 | 
			
		||||
    def before(self, station, date = None, qs = None):
 | 
			
		||||
        """
 | 
			
		||||
        Return a queryset of diffusions that finish before the given
 | 
			
		||||
        date.
 | 
			
		||||
        """
 | 
			
		||||
        date = utils.date_or_default(date)
 | 
			
		||||
        return self.filter(
 | 
			
		||||
        qs = qs or self
 | 
			
		||||
        return self.station(station, qs).filter(
 | 
			
		||||
            end__lte = date,
 | 
			
		||||
        ).order_by('start')
 | 
			
		||||
 | 
			
		||||
@ -1171,6 +1201,58 @@ class Port (models.Model):
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class LogManager(RelatedManager):
 | 
			
		||||
    def station(self, station, qs = None):
 | 
			
		||||
        qs = qs or self
 | 
			
		||||
        return qs.filter(station = station)
 | 
			
		||||
 | 
			
		||||
    def get_for(self, station, *args, **kwargs):
 | 
			
		||||
        qs = super().get_for(*args, **kwargs)
 | 
			
		||||
        return self.station(station, qs) if station else qs
 | 
			
		||||
 | 
			
		||||
    def _at(self, date = None, qs = None):
 | 
			
		||||
        start, end = utils.date_range(date)
 | 
			
		||||
        qs = qs or self
 | 
			
		||||
        return qs.filter(date__gte = start,
 | 
			
		||||
                         date__lte = end)
 | 
			
		||||
 | 
			
		||||
    def at(self, station = None, date = None, qs = None):
 | 
			
		||||
        """
 | 
			
		||||
        Return a queryset of logs that have the given date
 | 
			
		||||
        in their range.
 | 
			
		||||
        """
 | 
			
		||||
        qs = self._at(date, qs)
 | 
			
		||||
        return self.station(station, qs) if station else qs
 | 
			
		||||
 | 
			
		||||
    def at_for(self, station, date, object = None, model = None, qs = None):
 | 
			
		||||
        """
 | 
			
		||||
        Return a queryset of logs that occured at the given date
 | 
			
		||||
        for the given model or object.
 | 
			
		||||
        """
 | 
			
		||||
        qs = self.get_for(station, object, model, qs)
 | 
			
		||||
        return self._at(date, qs)
 | 
			
		||||
 | 
			
		||||
    def played(self, station, models, archives = True):
 | 
			
		||||
        """
 | 
			
		||||
        Return a queryset of the played elements' log for the given
 | 
			
		||||
        station and model. This queryset is ordered by date ascending
 | 
			
		||||
 | 
			
		||||
        * station: related station
 | 
			
		||||
        * models: a model or a list of models
 | 
			
		||||
        * archives: if false, exclude log of diffusion's archives from
 | 
			
		||||
            the queryset;
 | 
			
		||||
        """
 | 
			
		||||
        qs = self.get_for(station, model = models) \
 | 
			
		||||
                 .filter(type = Log.Type.play)
 | 
			
		||||
 | 
			
		||||
        if not archives and station.dealer:
 | 
			
		||||
            qs = qs.exclude(
 | 
			
		||||
                source = station.dealer.id,
 | 
			
		||||
                related_type = ContentType.objects.get_for_model(Sound)
 | 
			
		||||
            )
 | 
			
		||||
        return qs.order_by('date')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Log(Related):
 | 
			
		||||
    """
 | 
			
		||||
    Log sounds and diffusions that are played on the station.
 | 
			
		||||
@ -1206,14 +1288,14 @@ class Log(Related):
 | 
			
		||||
    station = models.ForeignKey(
 | 
			
		||||
        Station,
 | 
			
		||||
        verbose_name = _('station'),
 | 
			
		||||
        help_text = _('station on which the event occured'),
 | 
			
		||||
        help_text = _('related station'),
 | 
			
		||||
    )
 | 
			
		||||
    source = models.CharField(
 | 
			
		||||
        # we use a CharField to avoid loosing logs information if the
 | 
			
		||||
        # source is removed
 | 
			
		||||
        _('source'),
 | 
			
		||||
        max_length=64,
 | 
			
		||||
        help_text = _('source id that make it happen on the station'),
 | 
			
		||||
        help_text = _('identifier of the source related to this log'),
 | 
			
		||||
        blank = True, null = True,
 | 
			
		||||
    )
 | 
			
		||||
    date = models.DateTimeField(
 | 
			
		||||
@ -1226,6 +1308,8 @@ class Log(Related):
 | 
			
		||||
        blank = True, null = True,
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    objects = LogManager()
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def end(self):
 | 
			
		||||
        """
 | 
			
		||||
@ -1260,4 +1344,3 @@ class Log(Related):
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -59,7 +59,7 @@ def schedule_post_saved(sender, instance, created, *args, **kwargs):
 | 
			
		||||
    delta = instance.date - old_sched.date
 | 
			
		||||
 | 
			
		||||
    # update diffusions...
 | 
			
		||||
    qs = models.Diffusion.objects.get_after().filter(
 | 
			
		||||
    qs = models.Diffusion.objects.after(instance.program.station).filter(
 | 
			
		||||
        program = instance.program
 | 
			
		||||
    )
 | 
			
		||||
    for diff in qs:
 | 
			
		||||
@ -84,7 +84,7 @@ def schedule_pre_delete(sender, instance, *args, **kwargs):
 | 
			
		||||
        frequency = initial['frequency'],
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    qs = models.Diffusion.objects.get_after().filter(
 | 
			
		||||
    qs = models.Diffusion.objects.after(instance.program.station).filter(
 | 
			
		||||
        program = instance.program
 | 
			
		||||
    )
 | 
			
		||||
    for diff in qs:
 | 
			
		||||
 | 
			
		||||
@ -2,25 +2,51 @@ import datetime
 | 
			
		||||
import django.utils.timezone as tz
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def as_date(date, as_datetime = True):
 | 
			
		||||
def date_range(date):
 | 
			
		||||
    """
 | 
			
		||||
    If as_datetime, return the date with time info set to 0; else, return
 | 
			
		||||
    a date with date informations of the given date/time.
 | 
			
		||||
    Return a range of datetime for a given day, such as:
 | 
			
		||||
        [date, 0:0:0:0; date, 23:59:59:999]
 | 
			
		||||
 | 
			
		||||
    Ensure timezone awareness.
 | 
			
		||||
    """
 | 
			
		||||
    if as_datetime:
 | 
			
		||||
        return date.replace(hour = 0, minute = 0, second = 0, microsecond = 0)
 | 
			
		||||
    date = date_or_default(date)
 | 
			
		||||
    range = (
 | 
			
		||||
        date.replace(hour = 0, minute = 0, second = 0), \
 | 
			
		||||
        date.replace(hour = 23, minute = 59, second = 59, microsecond = 999)
 | 
			
		||||
    )
 | 
			
		||||
    return range
 | 
			
		||||
 | 
			
		||||
def cast_date(date, to_datetime = True):
 | 
			
		||||
    """
 | 
			
		||||
    Given a date reset its time information and
 | 
			
		||||
    return it as a date or datetime object.
 | 
			
		||||
 | 
			
		||||
    Ensure timezone awareness.
 | 
			
		||||
    """
 | 
			
		||||
    if to_datetime:
 | 
			
		||||
        return tz.make_aware(
 | 
			
		||||
            tz.datetime(date.year, date.month, date.day, 0, 0, 0, 0)
 | 
			
		||||
        )
 | 
			
		||||
    return datetime.date(date.year, date.month, date.day)
 | 
			
		||||
 | 
			
		||||
def date_or_default(date, no_time = False):
 | 
			
		||||
def date_or_default(date, reset_time = False, keep_type = False, to_datetime = True):
 | 
			
		||||
    """
 | 
			
		||||
    Return date or default value (now) if not defined, and remove time info
 | 
			
		||||
    if date_only is True
 | 
			
		||||
    Return datetime or default value (now) if not defined, and remove time info
 | 
			
		||||
    if reset_time is True.
 | 
			
		||||
 | 
			
		||||
    \param reset_time   reset time info to 0
 | 
			
		||||
    \param keep_type    keep the same type of the given date if not None
 | 
			
		||||
    \param to_datetime  force conversion to datetime if not keep_type
 | 
			
		||||
 | 
			
		||||
    Ensure timezone awareness.
 | 
			
		||||
    """
 | 
			
		||||
    date = date or tz.now()
 | 
			
		||||
    if no_time:
 | 
			
		||||
        return as_date(date)
 | 
			
		||||
    to_datetime = isinstance(date, tz.datetime) if keep_type else to_datetime
 | 
			
		||||
 | 
			
		||||
    if isinstance(date, datetime.datetime) and not tz.is_aware(date):
 | 
			
		||||
    if reset_time or not isinstance(date, tz.datetime):
 | 
			
		||||
        return cast_date(date, to_datetime)
 | 
			
		||||
 | 
			
		||||
    if not tz.is_aware(date):
 | 
			
		||||
        date = tz.make_aware(date)
 | 
			
		||||
    return date
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user