How can I calculate a date from the "created_at" property?

Highlighted
Tourist
26 0 1

Hello,

I'm new to Shopify, but I'd like to be able to include a date of "next Saturday" in my order confirmation emails. I've found that I could use the "created_at" property to return the date/time when the order was placed, but would I be able to do some calculation to find the date of the Saturday following the "created_at" date?

For example, if the order was placed on Tuesday 14th April, I'd like it to do something like this, written in no particular, made-up language...I'd presumably use something along the lines of:

{% for i in (Sunday..Saturday) %}
Clever stuff goes here
{% endfor %}

day = Tuesday (extracted from created_at)

date = 14th April (also extracted from created_at)

begin loop

if day = Saturday, exit loop and return date

else day = day + 1, date = date + 1

end loop

...and the result would be Saturday 18th April. Would something like this be possible in Shopify/Liquid?

 

Thank you in advance for any help or suggestions!

0 Likes
Highlighted
Shopify Partner
101 16 22

Hi @HelloPaul 

 

You will need to begin from the date of the order.

 

So:

{% assign date = order.created_at | date: '%s' %}

Where %s will return number of seconds since 1970-01-01 00:00:00 UTC.

 

We need to know which day of the week was the order made, for that we can use %w where this will return number from 0-6 where 0 is Monday and 6 is Sunday. 

{% assign day = order.created_at | date: '%w' %}

So we need to check now if the date of the order is Saturday or not:

{% if day == 5 %}
It's Saturday.
{% else %}
It's NOT Saturday.
{% endif %}

So if it's Saturday you can post the date there, but if it's not you need additional logic.

 

So if it's not we need to know how many days are we off until the closes Saturday. Since we now that Saturday is number 5 based on %w we can make a few calculations.

 

{% assign day_diff = 5 | minus: day  %}
{% if day_diff < 0 %}
  {% assign day_diff = 5 %}
{% endif %}

Where we are subtracting the day from the number 5 which will get us how many days are until the next Saturday. There is an if statement for Sunday, since that one will result to -1 and we overwrite it with 5.

 

Now once we know how many days are to the next Saturday we need to multiply those days by the seconds a single day have.

 

{% assign day_diff_seconds = day_diff | times: 24 | times: 60 | times: 60 %}

We are multiplying the days by 24 (for hours), 60 (for minutes) and 60 again (for seconds). This will give us the how many seconds we need to add to our initial date we converted to seconds.

 

So we should add them:

 

{% assign date = date | plus: day_diff_seconds %}

And finally we convert those seconds back to a date: 

 

{{date | date: '%Y-%m-%d' }}

So to sum it up in code it will fall down to this:

 

{% assign date = order.created_at | date: '%s' %}
{% assign day = order.created_at | date: '%w' %}

{% if day == 5 %}
  {{date | date: '%Y-%m-%d' }}
{% else %}
  {% assign day_diff = 5 | minus: day  %}
  {% if day_diff < 0 %}
    {% assign day_diff = 5 %}
  {% endif %}
  {% assign day_diff_seconds = day_diff | times: 24 | times: 60 | times: 60 %}
  {% assign date = date | plus: day_diff_seconds %}
  {{date | date: '%Y-%m-%d' }}
{% endif %}

The code is not tested but the logic should be clear.

 

 

Good luck!

0 Likes
Highlighted
Tourist
26 0 1

THANK YOU for all your help!

Just one thing - the result is the next Friday, not Saturday. I tried changing the occurrences of the 5s to 6s:

 

{% assign date = order.created_at | date: '%s' %}
{% assign day = order.created_at | date: '%w' %}

{% if day == 6  %}
  {{date | date: '%A, %e %B %Y %w' }}
{% else %}
  {% assign day_diff = 6 | minus: day  %}
  {% if day_diff < 0 %}
    {% assign day_diff = 6 is  %}
  {% endif %}
  {% assign day_diff_seconds = day_diff | times: 24 | times: 60 | times: 60 %}
  {% assign date = date | plus: day_diff_seconds %}
  {{date | date: '%A, %e %B %Y %w' }}
{% endif %}

 

...I tested it (today, Sunday 12 April) and the resulting day was Saturday 11 April, so simply changing all the 5s to 6s is clearly not the answer. I will go through your incredibly helpful explanation of what each step does once again, and see if I can figure it out!

Thanks again,

Paul

0 Likes
Highlighted
Shopify Partner
101 16 22

Hi @HelloPaul 

 

Try adding plus 1 to the diff_day after the calculation from my code.

 

Before this line:

{% assign day_diff_seconds = day_diff | times: 24 | times: 60 | times: 60 %}

Add the following:

{% assign day_diff = day_diff | plus: 1  %}

This should fix the issue.

0 Likes
Highlighted
Tourist
26 0 1

Thank you once again for your help with this! A couple more things...

 

The day numbering: You mentioned "...%w where this will return number from 0-6 where 0 is Monday and 6 is Sunday"
If I go to http://strftime.net/ and enter %w, it returns "2". It's Tuesday today, suggesting that 0 = Sunday, 1 = Monday...6 = Saturday. Could this be what's causing the discrepancy that you fixed with the additional "{% assign day_diff = day_diff | plus: 1 %}" line? I've also read that Python uses 0 = Sunday ... 6 = Saturday; I'd assume Liquid uses the same convention.

 

Also, I'd need to check the time. Because collection finishes at 13:00, I need to check if the order time's hour' is after 13. If so, the delivery date should be NEXT Saturday. This is what I've come up with (adding the line to assign the 24-hour-clock hour number to the 'hour' variable, and checking it's under 13 in the 'if' statement):

{% assign date = order.created_at | date: '%s' %}
{% assign day = order.created_at | date: '%w' %}
{% assign hour = order.created_at | date: '%k' %}

{% if day == 5 and hour < 13 %}
{{date | date: '%A, %e %B %Y' }}
{% else %}
{% assign day_diff = 5 | minus: day %}
{% if day_diff < 0 %}
{% assign day_diff = 5 %}
{% endif %}
{% assign day_diff = day_diff | plus: 1 %}
{% assign day_diff_seconds = day_diff | times: 24 | times: 60 | times: 60 %}
{% assign date = date | plus: day_diff_seconds %}
{{date | date: '%A, %e %B %Y' }}
{% endif %}

I'm guessing that should work?

0 Likes