AIRFLOW: use .replace() or relativedelta() in jinja template for {{ds}} - python

My goal is to return 1st day of previous month based on airflow macro variable {{ds}} and use it e.g. in HiveOperator.
E.g. For ds = 2020-05-09 I expect to return: 2020-04-01
The solution I found and tried were:
SET hivevar:LAST_MONTH='{{ (ds.replace(day=1) - macros.timedelta(days=1)).replace(day=1) }}';
SET hivevar:LAST_MONTH='{{ ds + macros.dateutil.relativedelta.relativedelta(months=-1, day=1) }}'
But both resulted in errors:
Error rendering template: replace() takes no keyword arguments
Error rendering template: must be str, not relativedelta
and when rendered didn't show any dates.
What am I doing wrong?

You can use:
{{ (execution_date + macros.dateutil.relativedelta.relativedelta(months=-1, day=1)).strftime("%Y-%m-%d") }}
Example:
from airflow.operators.bash_operator import BashOperator
default_args = {
'owner': 'airflow',
'start_date': datetime(2020, 4, 1),
}
with DAG(dag_id='stackoverflow',
default_args=default_args,
schedule_interval=None,
catchup=False
) as dag:
run_this = BashOperator(
task_id='example',
bash_command='echo ds is {{ ds }} modified ds is {{ (execution_date + macros.dateutil.relativedelta.relativedelta(months=-1, day=1)).strftime("%Y-%m-%d") }}',
)

According to airflow doc {{ execution_date }} is deprecated. So, you can keep using {{ ds }}, but you should convert it into datetime. Of course {{ ds }} depends on you cron time.
If you cron time is monthly, you could use only replace() function:
"{{ macros.datetime.strptime(ds, '%Y-%m-%d').replace(day=1) }}"
If you cron time is daily, use replace() and then relativedelta():
"{{ (macros.datetime.strptime(ds, '%Y-%m-%d').replace(day=1) - macros.dateutil.relativedelta.relativedelta(months=1)).strftime('%Y-%m-%d') }}

Related

The context processor that will pass the variable to the template year

I'm trying to write a context processor core.context_processors.year.year that will pass a variable year to the template, the value of which will be the current year as a number: © {{ year }} Copyright
from datetime import datetime, date
def year(request):
return {
request, datetime.now().date()
}
You need to return a dictionary, not a set. That dictionary should contain as key the name of the variable, and as value the value you want to associate with that, so here this will look like:
from django.utils.timezone import now
def year(request):
return {
'year': now().year
}
You can use the Built-in "now" templatetag https://docs.djangoproject.com/en/3.2/ref/templates/builtins/#now
© {% now "Y" %} Copyright
I figured out how to do it, initially I did it wrong. Thanks to everyone who responded.
from datetime import datetime
def year(request):
dt = datetime.now().year
return {
'year': dt
}

How do I convert seconds to hh:mm:ss in django template

So I have a dictionary called match. This has details of a match and one of the keys are game_time. If the game time is <= 10, the match is in draft. Else, I want to report the game time but the value its stored in is just in seconds.
{% if match.game_time <= 10 %}
drafting
{% else %}
{{match.game_time|date: "Z"}}
{% endif %}
Just gives me an error
Could not parse the remainder: ': "Z"' from 'match.game_time|date: "Z"'
any help appreciated
Use this formate for time
{{your_date_field|time:"h:i a"}}
from datetime import datetime, timedelta
def millisec_to_time(millisec):
d = datetime(1, 1, 1)+millisec
if d.day - 1 == 0:
return "{0}:{1}:{2}".format(d.hour, d.minute, d.second)
else:
return "{0}:{1}:{2}:{3}".format(d.day-1, d.hour, d.minute, d.second)
Try this to convert sec/msec to actual time.
If you install mathfilters, add it to your install_apps, and load it into your template then you can do this.
{{ booking.duration|div:3600|floatformat:"2" }}

Why do my dates and times differ?

I have in my jinja2 template code for localization.
{% set currency = "SEK" %}
{% set format = "sv_SE" %}
{% set timezoneinfo = 'Europe/Stockholm' %}
{% set locale = "se" %}
But it's not working for hours and minutes if I use it like this with a filter using values from a google search API result to filter.
{{scored_document.fields.10.value|datetimeformat_list(hour=scored_document.fields.17.value|int ,minute =scored_document.fields.18.value|int, timezoneinfo=timezoneinfo, locale=locale)}}
filter
def datetimeformat_list(date, hour, minute, locale='en', timezoneinfo='Asia/Calcutta'):
tzinfo = timezone(timezoneinfo)
input = datetime(date.year, date.month, date.day, int(hour), int(minute), tzinfo=tzinfo)
time_str = format_time(input, 'H:mm', tzinfo=tzinfo, locale=locale)
return "{0}".format(time_str)
The code gives a different time than if I just do
{{ ad.modified|datetimeformat_viewad(locale='se', timezoneinfo='Europe/Stockholm') }}
with this filter
def datetimeformat_viewad(to_format, locale='en', timezoneinfo='Asia/Calcutta'):
tzinfo = timezone(timezoneinfo)
month = MONTHS[to_format.month - 1]
date_str = '{0} {1}'.format(to_format.day, _(month))
time_str = format_time(to_format, 'H:mm', tzinfo=tzinfo, locale=locale)
return "{0} {1}".format(date_str, time_str)
Why are the outputs not the same time?
It is incorrect to pass an arbitrary pytz timezone to datetime constructor directly; you should use pytz_tzinfo.localize() method instead as it is said at the very beginning of pytz docs.
There could be other issues in your code.

Converting UNIX time to datetime object in Jinja templates

I want to convert my timestamp to datetime in jinja2..
here's my sample code:
import time
date = time.time()
self.tv['date'] = date
sample html:
<p>{{ date }}</p>
I want to convert it to datetime using jinja2 in python..
thanks..
Make a custom filter like
#app.template_filter('ctime')
def timectime(s):
return time.ctime(s) # datetime.datetime.fromtimestamp(s)
And use your template filter
{{ date | ctime }}
You convert it before passing it to a template, eg:
>>> import time
>>> date = time.time()
>>> from datetime import datetime
>>> datetime.fromtimestamp(date)
datetime.datetime(2013, 3, 1, 2, 57, 29, 472572)
And optionally use formatting:
>>> format(datetime.fromtimestamp(date), '%Y%m%d')
'20130301'
Use this in the template:
{{ time | from_timestamp('%Y.%m.%d. %H:%M:%S UTC') }}
Use the following,
Data
{
"timestamp": "1424197820"
}
Template
{{ timestamp|timestamp_to_time|datetimeformat('%a, %B %d') }}
Rendered
Tue, February 17
Source

Add one day in time from database in django

Hi,
I need to add some condition on the time base , right now the value of time i am getting from database is like 2012-09-05 05:05:05 and i need to add 24 hours in this.
I need to show different content on time base, like for original time i need to show "hi" and after 24 hours i need to show "hello" in the template file.
How can i do this? Please help me.
probably a custom template tag would be a nice way: https://docs.djangoproject.com/en/dev/howto/custom-template-tags/#writing-custom-template-filters . you could implement your own deltaDays tag with parameters, i.e. {{ date|deltaDays:1 }}.
You could also do this as a cheap filter.
from django import template
register = template.Library()
#register.filter()
def is_at_least_24_hours_ago(value):
import datetime
original_date_plus_24 = value + datetime.timedelta(hours=24)
right_now = datetime.datetime.now()
if right_now >= original_date_plus_24:
return True
return False
Then in your template:
{% if object_date|is_at_least_24_hours_ago %}
// It's 24 hours later
{% else %}
// It's not
{% endif %}
This is sample on how to add day(s),
import datetime
b = var_name + datetime.timedelta(0,3) # days, seconds
or
datetime.timedelta(days=1)
pass the value through view then use if statement in your template

Categories