Jekyll using pipe operator in where_exp - filtering

I am using Jekyll 3.8. My posts contain date attribute set. Some of them contain values from the past (e.g. 2001-01-01), some of them from the future (e.g. 2109-12-31).
What I would like to achieve is to display only posts that are in the past (so that their date is smaller than now). Now, I've managed to get it done using:
{% capture current_time %}{{'now' | date: '%s'}}{% endcapture %}
{% for post in site.posts %}
{% capture post_time %}{{post.date | date: '%s'}}{% endcapture %}
{% if post_time >= current_time %}
DISPLAY THE ITEM
{% endif %}
{% endfor %}
but it's not efficient.
I would like to have it done using where_exp filter. Now - is it possible?
My draft looks like:
{% capture current_time %}{{'now' | date: '%s'}}{% endcapture %}
{% assign filtered_posts = site.posts| where_exp:"post","post.date | date: '%s' >= current_time" %}
{% for post in filtered_posts %}
DISPLAY THE ITEM
{% endfor %}
but I'm receiving Liquid Exception: Liquid error (line 5): comparison of Time with String failed in source.md.
I suppose, that the problem lies in | date: '%s' from {% assign filtered_posts = site.posts| where_exp:"post","post.date | date: '%s' >= current_time" %}.
Therefore:
can I even use filters (pipe) in the where_exp expressions?
If not, then - can I somehow cast the post.date to string without filters, or cast current_time to string and make the comparision work at the same time?

I had a similar problem, which I described in detail in the Jekyll community forum. It is about getting a list of future events including today, and the OP's similar approach did not work here as well:
{% assign events_list = site.events | where_exp: "event", "event.date >= site.time | date: %F" %}
So I created a filter plugin in _plugins/to_time.rb, which converts a string to a Time object:
module Jekyll
module AssetFilter
def to_time(date_string)
DateTime.parse(date_string).to_time
end
end
end
Liquid::Template.register_filter(Jekyll::AssetFilter)
This first parses the string to a DateTime object and then uses this to_time function to make a Time object.
Then I assign a variable with the current time, apply the pipe operator with the filter I need, and then I add the to_time filter in the end:
{% assign today = 'now' | date: '%F' | to_time %}
Using now, then using %F to just get the date part of it, then converting it back to Time, so today will be todays date at 0:00 in the morning.
Then I can compare it with the date object from my events collection items:
{% assign events_list = site.events | where_exp: "event", "event.date >= today" %}

I cannot reproduce your error as where_exp is throwing an error because of the pipe in the comparison expression.
Nevertheless, you can compare post.date which is a Time object to site.time (generation time) to get posts that are in the past.
{% assign filtered_posts = site.posts | where_exp: "post","post.date <= site.time" %}

Related

How to get current date in Helm

I need to get the current date in Helm with the following format YY-MM-DD. I'm trying {{ now | date }} but this returns an error because the number of arguments expected by date is two, not one.
Try Format the date to YEAR-MONTH-DAY:
{{ now | date "20060102150405" }}
Source here:
or add the following annotation :
annotations:
deploymentTime: {{ now | date "2006-01-02T15:04:05" }}

Hugo, how to localized .groupByDate

In my template I sort by months my post like this:
{{ range (where site.RegularPages "Type" "in" site.Params.mainSections).GroupByDate "January, 2006" -}}
<h1>{{ .Key }}</h1> // output: March, 2022
{{ range (where .Pages ".Params.unlisted" "!=" "true") }}
<div>{{ time.Format "02 January" .Date }} - {{ .Title }}</div> // output: 01 Mars - This is the title of my post
{{ end }}
{{ end }}
For every post the time.Format localized my date in my language (here in French).
But the title witch is group by month is still in English (here it's the h1). How can I format my {{ .Key }} so it can be localized in my own language and show "Mars, 2022" instead of "March, 2022" ?
How about:
{{ time.Format "02 January" .Key }}
Or is there something I am missing?
Update: You can sort by months like this:
{{ range (where site.RegularPages "Type" "in" site.Params.mainSections).GroupByDate "1 2006" -}}
Then you can split your .Key by a space and create a manual lookup for your localized month. Not very pretty, but it gets the job done.
Since hugo version 0.97 it works as expected, we don't need some ugly hack to have the text in the corresponding language.
Now you can use .GroupByDate and it will use your language settings in your config file.

How to prevent duplicate blog post dates in shopify

I have a blog with posts on a shopify website. I want to get all the publication dates of posts, and I do it like this:
{% for article in blog.articles %}
{{ article.created_at }}
{% endfor %}
And this is the output result:
2022-02-01 14:50:06
2022-01-25 05:25:33
2022-01-25 05:24:48
The result shows that there are two posts with the date 2022-01-25 and one post with the date 2022-02-01. But all these dates have different seconds and minutes.
I want to remove seconds and minutes by setting the format to date: "%B %Y":
{{ article.created_at | date: "%B %Y" }}
And in the end I get this result:
February 2022
January 2022
January 2022
Now the question is: How do I prevent duplicate dates with the same format date: "%B %Y"?
I can easily solve this problem with javascript, but I want to know if it's possible to solve this problem using only shopify features.
I will be glad to any answer. Thanks!
You can store all the dates in as string
{%- capture dates -%}
{%- for article in blog.articles -%}
{{ article.created_at | date: "%B %Y" }},
{%- endfor -%}
{%- endcapture -%}
And split and uniq the values to get only the unique ones:
{% assign unique_dates = dates | split: ',' | uniq %}
This will remove any values that are repeating.
Hope this is what you are looking for.

Date comparison Logic / in Liquid Filter

I'm trying to add 30 days to a pre-order date and if today's date is later, display a text string and if not display another text string. Any ideas where I'm going wrong?
{% assign assign pre_date = 259200 | plus: order.created_at | date: '%s' %}
{% assign today_date = 'now' | date: '%s' %}
{% if pre_date > today_date %}
disply this
{% else %}
this
{% endif %}
The date filter returns a string, even when you're using %s to get a number of seconds, so Shopify may be running into situations where you're comparing strings-that-look-like numbers instead of actual numbers
To coerce your variables into their proper numeric values, I find the simplest thing to do is to apply a neutral mathematical operation (either | plus: 0 or | times: 1)
So your final code might look something like:
{% assign pre_date = order.created_at | date: '%s' | plus: 259200 %}
{% assign today_date = 'now' | date: '%s' | times: 1 %}
{% if pre_date > today_date %}
Pre-date is greater
{% else %}
Today is the day
{% endif %}

Fluid compare dates

I want to compare two dates. I want to make a condition which checks if the date in my database is older than the date in two days.
Here are my two variables:
{<f:format.date format="d.m.Y">+2 days</f:format.date>}
{<f:format.date format="d.m.Y">{day.valid}</f:format.date>}
I want to solve this in the template, not in the model or the controller.
Assign your date to variable »yourdate«.
<f:if condition="{f:format.date(date: '+2 days', format: 'Y-m-d')} < {f:format.date(date: yourdate, format: 'Y-m-d')}">
<f:then>
yourdate is smaller than now + 2 days.
</f:then>
<f:else>
yourdate is greater than or equal to now + 2 days.
</f:else>
</f:if>
Here is my current solution which adds in a current date and does some calculations with the date from the content.
In the controller, add the current date to the data:
$this->view->assign('date_now', new \DateTime());
This is available as {date_now} in fluid then:
<f:if condition="{f:format.date(date: date_now, format: '(Y-m-d)')} > {f:format.date(date: '{event.date}-4 weeks', format: '(Y-m-d)')}">
<f:then>
<p>Event date is past</p>
</f:then>
<f:else>
<p>Event date is upcoming</p>
</f:else>
</f:if>
Note how on the right side, where some calculation is done, additional quotes and curly brackets come in ('{event.date}-4 weeks').
PS I prefer the Y-m-d format to U for a date comparison, as we don't want to compare the current time – just the date.
Convert the date to an unix timestamp using format="U" and compare them. You need to add a variable which contains the comparing date.
<f:if condition="{f:format.date(date: day.valid, format: 'U')} > {f:format.date(date: date_compare, format: 'U')}">
Date is valid
</f:if>
Actually: because DateTime has a getTimestamp method (http://php.net/manual/en/datetime.gettimestamp.php, since 5.3.0) which perfectly conforms to the supported getter method naming in Fluid, the following is perfectly possible. Given $date1 and $date2 are both DateTime instances assigned to the template:
<f:if condition="{date1.timestamp} < {date2.timestamp}">...</f:if>
Will compare the two dates as unix timestamp integers without the need to format the dates. So for your case, assign a $date = (new \DateTime('now'))->modify('+2 days'); from your controller action and compare to that in Fluid. Or just assign the time() timestamp and compare directly to that, skipping the DateTime usage.