def __init__(self, *, target_time: Union[str, datetime.datetime], **kwargs) -> None: super().__init__(**kwargs) if isinstance(target_time, datetime.datetime): if timezone.is_naive(target_time): target_time = timezone.make_aware(target_time) self.target_time = target_time elif isinstance(target_time, str): self.target_time = timezone.parse(target_time) else: raise TypeError( f"Expected str or datetime.datetime type for target_time. Got {type(target_time)}" )
def date_range(start_date, end_date=None, num=None, delta=None): """ Get a set of dates as a list based on a start, end and delta, delta can be something that can be added to ``datetime.datetime`` or a cron expression as a ``str`` :param start_date: anchor date to start the series from :type start_date: datetime.datetime :param end_date: right boundary for the date range :type end_date: datetime.datetime :param num: alternatively to end_date, you can specify the number of number of entries you want in the range. This number can be negative, output will always be sorted regardless :type num: int >>> date_range(datetime(2016, 1, 1), datetime(2016, 1, 3), delta=timedelta(1)) [datetime.datetime(2016, 1, 1, 0, 0), datetime.datetime(2016, 1, 2, 0, 0), datetime.datetime(2016, 1, 3, 0, 0)] >>> date_range(datetime(2016, 1, 1), datetime(2016, 1, 3), delta='0 0 * * *') [datetime.datetime(2016, 1, 1, 0, 0), datetime.datetime(2016, 1, 2, 0, 0), datetime.datetime(2016, 1, 3, 0, 0)] >>> date_range(datetime(2016, 1, 1), datetime(2016, 3, 3), delta="0 0 0 * *") [datetime.datetime(2016, 1, 1, 0, 0), datetime.datetime(2016, 2, 1, 0, 0), datetime.datetime(2016, 3, 1, 0, 0)] """ if not delta: return [] if end_date and start_date > end_date: raise Exception("Wait. start_date needs to be before end_date") if end_date and num: raise Exception("Wait. Either specify end_date OR num") if not end_date and not num: end_date = timezone.utcnow() delta_iscron = False if isinstance(delta, six.string_types): delta_iscron = True tz = start_date.tzinfo start_date = timezone.make_naive(start_date, tz) cron = croniter(delta, start_date) elif isinstance(delta, timedelta): delta = abs(delta) l = [] if end_date: while start_date <= end_date: if timezone.is_naive(start_date): l.append(timezone.make_aware(start_date, tz)) else: l.append(start_date) if delta_iscron: start_date = cron.get_next(datetime) else: start_date += delta else: for _ in range(abs(num)): if timezone.is_naive(start_date): l.append(timezone.make_aware(start_date, tz)) else: l.append(start_date) if delta_iscron: if num > 0: start_date = cron.get_next(datetime) else: start_date = cron.get_prev(datetime) else: if num > 0: start_date += delta else: start_date -= delta return sorted(l)
def test_is_naive(self): self.assertFalse( timezone.is_naive( datetime.datetime(2011, 9, 1, 13, 20, 30, tzinfo=EAT))) self.assertTrue( timezone.is_naive(datetime.datetime(2011, 9, 1, 13, 20, 30)))
def date_range( start_date: datetime, end_date: Optional[datetime] = None, num: Optional[int] = None, delta: Optional[Union[str, timedelta, relativedelta]] = None, ) -> List[datetime]: """ Get a set of dates as a list based on a start, end and delta, delta can be something that can be added to `datetime.datetime` or a cron expression as a `str` .. code-block:: pycon >>> from airflow.utils.dates import datterange >>> from datetime import datetime, timedelta >>> date_range(datetime(2016, 1, 1), datetime(2016, 1, 3), delta=timedelta(1)) [datetime.datetime(2016, 1, 1, 0, 0, tzinfo=Timezone('UTC')), datetime.datetime(2016, 1, 2, 0, 0, tzinfo=Timezone('UTC')), datetime.datetime(2016, 1, 3, 0, 0, tzinfo=Timezone('UTC'))] >>> date_range(datetime(2016, 1, 1), datetime(2016, 1, 3), delta="0 0 * * *") [datetime.datetime(2016, 1, 1, 0, 0, tzinfo=Timezone('UTC')), datetime.datetime(2016, 1, 2, 0, 0, tzinfo=Timezone('UTC')), datetime.datetime(2016, 1, 3, 0, 0, tzinfo=Timezone('UTC'))] >>> date_range(datetime(2016, 1, 1), datetime(2016, 3, 3), delta="0 0 0 * *") [datetime.datetime(2016, 1, 1, 0, 0, tzinfo=Timezone('UTC')), datetime.datetime(2016, 2, 1, 0, 0, tzinfo=Timezone('UTC')), datetime.datetime(2016, 3, 1, 0, 0, tzinfo=Timezone('UTC'))] :param start_date: anchor date to start the series from :param end_date: right boundary for the date range :param num: alternatively to end_date, you can specify the number of number of entries you want in the range. This number can be negative, output will always be sorted regardless :param delta: step length. It can be datetime.timedelta or cron expression as string """ warnings.warn( "`airflow.utils.dates.date_range()` is deprecated. Please use `airflow.timetables`.", category=DeprecationWarning, stacklevel=2, ) if not delta: return [] if end_date: if start_date > end_date: raise Exception("Wait. start_date needs to be before end_date") if num: raise Exception("Wait. Either specify end_date OR num") if not end_date and not num: end_date = timezone.utcnow() delta_iscron = False time_zone = start_date.tzinfo abs_delta: Union[timedelta, relativedelta] if isinstance(delta, str): delta_iscron = True if timezone.is_localized(start_date): start_date = timezone.make_naive(start_date, time_zone) cron = croniter(cron_presets.get(delta, delta), start_date) elif isinstance(delta, timedelta): abs_delta = abs(delta) elif isinstance(delta, relativedelta): abs_delta = abs(delta) else: raise Exception( "Wait. delta must be either datetime.timedelta or cron expression as str" ) dates = [] if end_date: if timezone.is_naive(start_date) and not timezone.is_naive(end_date): end_date = timezone.make_naive(end_date, time_zone) while start_date <= end_date: # type: ignore if timezone.is_naive(start_date): dates.append(timezone.make_aware(start_date, time_zone)) else: dates.append(start_date) if delta_iscron: start_date = cron.get_next(datetime) else: start_date += abs_delta else: num_entries: int = num # type: ignore for _ in range(abs(num_entries)): if timezone.is_naive(start_date): dates.append(timezone.make_aware(start_date, time_zone)) else: dates.append(start_date) if delta_iscron and num_entries > 0: start_date = cron.get_next(datetime) elif delta_iscron: start_date = cron.get_prev(datetime) elif num_entries > 0: start_date += abs_delta else: start_date -= abs_delta return sorted(dates)
from airflow import DAG from airflow.utils import timezone from airflow.operators.dummy_operator import DummyOperator from datetime import timedelta, datetime local_tz = pendulum.timezone("Europe/Paris") default_args = { 'start_date': datetime(2021, 3, 29, 2, tzinfo=local_tz), 'owner': 'Airflow', 'email': "*****@*****.**" } with DAG(dag_id='tz_dag', schedule_interval="0 2 * * *", default_args=default_args) as dag: dummy_task = DummyOperator(task_id='dummy_task') run_dates = dag.get_run_dates(start_date=dag.start_date) next_execution_date = run_dates[-1] if len(run_dates) != 0 else None # Uncomment when you use the DAG, comment when not print('datetime from Python is Naive: {0}'.format(timezone.is_naive(datetime(2019, 9, 19)))) print('datetime from Airflow is Aware: {0}'.format(timezone.is_naive(timezone.datetime(2019, 9, 19)) == False)) print('[DAG:tz_dag] timezone: {0} - start_date: {1} - schedule_interval: {2} - Lastest execution_date: {3} - next execution_date {4} in UTC - next execution_date {5} in local time'.format( dag.timezone, dag.default_args['start_date'], dag.schedule_interval, dag.latest_execution_date, next_execution_date, local_tz.convert(next_execution_date) if next_execution_date is not None else None ))
from airflow.utils import timezone from airflow.operators.dummy_operator import DummyOperator from datetime import timedelta, datetime local_tz = pendulum.timezone("Europe/Paris") default_args = {'start_date': datetime(2019, 3, 29, 1), 'owner': 'Airflow'} with DAG(dag_id='tz_dag', schedule_interval="0 1 * * *", default_args=default_args) as dag: dummy_task = DummyOperator(task_id='dummy_task') run_dates = dag.get_run_dates(start_date=dag.start_date) next_execution_date = run_dates[-1] if len(run_dates) != 0 else None # Uncomment when you use the DAG, comment when not # use docker logs -f docker_ID to see print statements below print('datetime from Python is Naive: {0}'.format( timezone.is_naive(datetime(2019, 9, 19)))) print('datetime from Airflow is Aware: {0}'.format( timezone.is_naive(timezone.datetime(2019, 9, 19)) == False)) print( '[DAG:tz_dag] timezone: {0} - start_date: {1} - schedule_interval: {2} - Last execution_date: {3} - next execution_date {4} in UTC - next execution_date {5} in local time' .format( dag.timezone, dag.default_args['start_date'], dag._schedule_interval, dag.latest_execution_date, next_execution_date, local_tz.convert(next_execution_date) if next_execution_date is not None else None))
def date_range(start_date, end_date=None, num=None, delta=None): # pylint: disable=too-many-branches """ Get a set of dates as a list based on a start, end and delta, delta can be something that can be added to `datetime.datetime` or a cron expression as a `str` .. code-block:: python date_range(datetime(2016, 1, 1), datetime(2016, 1, 3), delta=timedelta(1)) [datetime.datetime(2016, 1, 1, 0, 0), datetime.datetime(2016, 1, 2, 0, 0), datetime.datetime(2016, 1, 3, 0, 0)] date_range(datetime(2016, 1, 1), datetime(2016, 1, 3), delta='0 0 * * *') [datetime.datetime(2016, 1, 1, 0, 0), datetime.datetime(2016, 1, 2, 0, 0), datetime.datetime(2016, 1, 3, 0, 0)] date_range(datetime(2016, 1, 1), datetime(2016, 3, 3), delta="0 0 0 * *") [datetime.datetime(2016, 1, 1, 0, 0), datetime.datetime(2016, 2, 1, 0, 0), datetime.datetime(2016, 3, 1, 0, 0)] :param start_date: anchor date to start the series from :type start_date: datetime.datetime :param end_date: right boundary for the date range :type end_date: datetime.datetime :param num: alternatively to end_date, you can specify the number of number of entries you want in the range. This number can be negative, output will always be sorted regardless :type num: int :param delta: step length. It can be datetime.timedelta or cron expression as string :type delta: datetime.timedelta or str """ if not delta: return [] if end_date and start_date > end_date: raise Exception("Wait. start_date needs to be before end_date") if end_date and num: raise Exception("Wait. Either specify end_date OR num") if not end_date and not num: end_date = timezone.utcnow() if delta in cron_presets: delta = cron_presets.get(delta) delta_iscron = False time_zone = start_date.tzinfo if isinstance(delta, str): delta_iscron = True if timezone.is_localized(start_date): start_date = timezone.make_naive(start_date, time_zone) cron = croniter(delta, start_date) elif isinstance(delta, timedelta): delta = abs(delta) else: raise Exception( "Wait. delta must be either datetime.timedelta or cron expression as str" ) dates = [] if end_date: if timezone.is_naive(start_date) and not timezone.is_naive(end_date): end_date = timezone.make_naive(end_date, time_zone) while start_date <= end_date: if timezone.is_naive(start_date): dates.append(timezone.make_aware(start_date, time_zone)) else: dates.append(start_date) if delta_iscron: start_date = cron.get_next(datetime) else: start_date += delta else: for _ in range(abs(num)): if timezone.is_naive(start_date): dates.append(timezone.make_aware(start_date, time_zone)) else: dates.append(start_date) if delta_iscron and num > 0: start_date = cron.get_next(datetime) elif delta_iscron: start_date = cron.get_prev(datetime) elif num > 0: start_date += delta else: start_date -= delta return sorted(dates)
def date_range( start_date, end_date=None, num=None, delta=None): """ Get a set of dates as a list based on a start, end and delta, delta can be something that can be added to ``datetime.datetime`` or a cron expression as a ``str`` :param start_date: anchor date to start the series from :type start_date: datetime.datetime :param end_date: right boundary for the date range :type end_date: datetime.datetime :param num: alternatively to end_date, you can specify the number of number of entries you want in the range. This number can be negative, output will always be sorted regardless :type num: int >>> date_range(datetime(2016, 1, 1), datetime(2016, 1, 3), delta=timedelta(1)) [datetime.datetime(2016, 1, 1, 0, 0), datetime.datetime(2016, 1, 2, 0, 0), datetime.datetime(2016, 1, 3, 0, 0)] >>> date_range(datetime(2016, 1, 1), datetime(2016, 1, 3), delta='0 0 * * *') [datetime.datetime(2016, 1, 1, 0, 0), datetime.datetime(2016, 1, 2, 0, 0), datetime.datetime(2016, 1, 3, 0, 0)] >>> date_range(datetime(2016, 1, 1), datetime(2016, 3, 3), delta="0 0 0 * *") [datetime.datetime(2016, 1, 1, 0, 0), datetime.datetime(2016, 2, 1, 0, 0), datetime.datetime(2016, 3, 1, 0, 0)] """ if not delta: return [] if end_date and start_date > end_date: raise Exception("Wait. start_date needs to be before end_date") if end_date and num: raise Exception("Wait. Either specify end_date OR num") if not end_date and not num: end_date = timezone.utcnow() delta_iscron = False tz = start_date.tzinfo if isinstance(delta, six.string_types): delta_iscron = True start_date = timezone.make_naive(start_date, tz) cron = croniter(delta, start_date) elif isinstance(delta, timedelta): delta = abs(delta) dates = [] if end_date: if timezone.is_naive(start_date): end_date = timezone.make_naive(end_date, tz) while start_date <= end_date: if timezone.is_naive(start_date): dates.append(timezone.make_aware(start_date, tz)) else: dates.append(start_date) if delta_iscron: start_date = cron.get_next(datetime) else: start_date += delta else: for _ in range(abs(num)): if timezone.is_naive(start_date): dates.append(timezone.make_aware(start_date, tz)) else: dates.append(start_date) if delta_iscron: if num > 0: start_date = cron.get_next(datetime) else: start_date = cron.get_prev(datetime) else: if num > 0: start_date += delta else: start_date -= delta return sorted(dates)
def test_is_naive(self): self.assertFalse(timezone.is_naive(datetime.datetime(2011, 9, 1, 13, 20, 30, tzinfo=EAT))) self.assertTrue(timezone.is_naive(datetime.datetime(2011, 9, 1, 13, 20, 30)))
def _default(obj): """Convert dates and numpy objects in a json serializable format.""" if isinstance(obj, datetime): if is_naive(obj): obj = convert_to_utc(obj) return obj.isoformat() elif isinstance(obj, date): return obj.strftime('%Y-%m-%d') elif isinstance(obj, Decimal): _, _, exponent = obj.as_tuple() if exponent >= 0: # No digits after the decimal point. return int(obj) # Technically lossy due to floating point errors, but the best we # can do without implementing a custom encode function. return float(obj) elif np is not None and isinstance( obj, ( np.int_, np.intc, np.intp, np.int8, np.int16, np.int32, np.int64, np.uint8, np.uint16, np.uint32, np.uint64, ), ): return int(obj) elif np is not None and isinstance(obj, np.bool_): return bool(obj) elif np is not None and isinstance( obj, (np.float_, np.float16, np.float32, np.float64, np.complex_, np.complex64, np.complex128)): return float(obj) elif k8s is not None and isinstance( obj, (k8s.V1Pod, k8s.V1ResourceRequirements)): from airflow.kubernetes.pod_generator import PodGenerator def safe_get_name(pod): """ We're running this in an except block, so we don't want it to fail under any circumstances, e.g. by accessing an attribute that isn't there """ try: return pod.metadata.name except Exception: return None try: return PodGenerator.serialize_pod(obj) except Exception: log.warning("JSON encoding failed for pod %s", safe_get_name(obj)) log.debug("traceback for pod JSON encode error", exc_info=True) return {} raise TypeError( f"Object of type '{obj.__class__.__name__}' is not JSON serializable" )
def test_is_naive(self): assert not timezone.is_naive(datetime.datetime(2011, 9, 1, 13, 20, 30, tzinfo=EAT)) assert timezone.is_naive(datetime.datetime(2011, 9, 1, 13, 20, 30))