REST to GraphQL order timezone issue

Hello,

We have been facing an issue with timezones since we migrated from REST to GraphQL (as strongly advised by Shopify).
While REST API used to return customer timezone in orders (created_at field), for some reason GraphQL now returns a UTC date (createdAt). This is very bothersome as we want our analytics app to reflect Shopify reports which use customer’s timezone to calculate daily sales.
While before we could perfectly align our results to Shopify’s reports, we now have timezone gaps and data is desync.

We tried to:

  • Use Shop’s timezone: not usefull as some countries have multiple timezones (ex: USA)
  • Use Customer shipping address timeZone: seems to not always be aligned with REST customer timezone
  • Calculate timezone with longitude and latitude values: prone to error because of some geographical singularities.

So now we have been stuck for months with analytics gaps which make our data correctness controls very hard.

Why wouldn’t GraphQL provide the customer timezone as REST used to? I don’t see any trouble with sending two fields, something like “createdAt” and “createdAtLocal” would do the job.

If you have any insights on this, thank you.

1 Like

Hey Jeremie,

I’ve connected with our orders team internally to see if they have a recommendation on how to account for this. Will update ASAP.

1 Like

Hi again Jeremie,

I’ve connected with the product team on this and they’ve confirmed that the created_at is stored in UTC and we can return it in any timezone, it’s usually the shop-locale that’s configured.

Any analytics tool worth their salt should be able to convert from UTC to a timezone.

If you’re data is a mix due to data coming from different integrations, then the issue is in your integration and you should handle the conversion as needed. It’s in the docs.

It’s the “usually” that is bothering us. We tried these approaches and we always end up with a discrepancy when comparing with Shopify reports. Maybe it would help to know what timezone is REST using when storing the created_at field.

Let’s take the example of our US store with a customer located in Canada, shipping to Texas, when our shop’s timezone is New York, knowing that there might be some Daylight Saving Time on the way? Which timezone is used?

Calculating this on our end looks like some back-engineering that would be solved so simply if Shopify returned the local timezone as it used to in REST.

I don’t understand your answer.

How do you convert from UTC to a timezone if you don’t know the timezone of the customer? As I said, the timezone of a customer is not necessarily the shop’s timezone, nor the shipping address timezone.
And our analytics tool has been gathering data for our 15 different countries for years now, so no, I don’t think it’s “in our integration”. Not all issues can be solved by “it’s in the docs”.

Hey @Jeremie_SAVON

Shopify reports which use customer’s timezone to calculate daily sales.

Do they use the customer’s or the merchant’s (shop) timezone?

To calculate daily sales in the merchant’s timezone, we first convert the merchant’s midnight (00:00) to UTC, then gather the orders and sum up those within the range.

By the way, we use processed_at instead of created_at because the REST API documentation states that processed_at is used in analytical reports: Order - REST

I think you’re right, it might be the merchant’s timezone. So I guess my issue is with Daylight Saving Time changes. In US, sometime I will get -08:00, sometimes -07:00.
So let’s say right now, my shop is -08:00, but I’m converting an order from a period when it was -07:00, then I get a discrepancy.
Solving this on our end would mean for us to know DST for each date of the year.

As far as I remember, when you use GraphQL, everything is correctly converted to UTC by shopify, so you don’t need to worry about the time zone changes. You’re probably referring to the unusual behavior related to time zone shifts described here:

It’s better to use the iana_timezone on the Shop resource rather than the timezone field:

Shopify may update the timezone with a delay, which caused issues in the past on our end, so it’s safer to rely on the IANA time zone.

If you’re in the JS world, you can use Luxon.

To find your boundaries in UTC

  1. Set your time to the customer’s IANA time zone.
  2. Set Date as you want.
  3. Retrieve the midnight time in that time zone with functions such as .startOf(‘day’)
  4. Convert the time to UTC and format as ISO 8601 to use directly in graphql.

Then you can then either filter using min and max values via GraphQL or compare them directly with the processedAt value in the GraphQL orders.

Now you don’t need to worry about fixed offset zones. In the end, you can simply convert these UTC dates to the IANA timezone of your merchant if necessary.

I would highly recommend using UTC datetimes everywhere in your app, and then when displaying it to the customer using something like Intl.DateTimeFormat - JavaScript | MDN

Which will convert the dates to the customers timezone and format in the browser. This means you can keep everything simple within your app as you know it’ll be UTC, but still display it in the relevant timezone to your customer.

Also this API is baked into the browser, so no external dependencies or performance concerns.

I think there is a misunderstanding of what we call “customers”.
What I meant by customer is the the person who placed the order, not the client who will watch my analytics dashboard.

If I store dates in UTC as you are advising, I will then get everything I’m fighting against and the topic of this post which is: tracing back the order date to the real timezone of the customer.
If you store everything in UTC, you will not be able to get 100% sync with Shopify’s reports as there will be discrepancies the moment you convert all the orders to the same timezone.

For example, you store everything in UTC, then want to use US timezone. You then convert all the UTC dates to one of US numerous timezones (ideally your store’s timezone), but get different results (most likely because of DST)

1 Like

I feel like everybody is trying to help but maybe never faced the issue themselves.
Maybe with a real example it will get clearer:

Image 1 is my shop current’s timezone. You can see it is “-08:00”.

Image 2 is an order from Nov 3rd, stored in local timezone by Shopify in REST.
You can see it is “-07:00”.

Image 3 is a recent order. You can see it is “-08:00”.

Now with this info, you can easily see that

  1. you can get different timezones in the same shop
  2. you can’t trace back an order to a timezone using only UTC date
  3. to trace back successfully you have to know what was the shop’s timezone at the time of the order, which is not realistic

Does somebody have a solution for this? Thank you!

I took a look back at the API docs to see if there was anything. Sorry for miss understanding customers, it’s certainly an overloaded term :see_no_evil:

You do have access to the clients IP address and customer locale, so could you infer the timezone from that? :thinking:

Hello Jordan, thank you for your response. I thought of that before but I don’t think it works as the customer could be in another location (let’s say Europe) when placing an order on the US store. Also, I think Shopify uses the store timezone (as discussed in a previous message in this thread) instead of the customer timezone, which can be different.

I think I came up with a solution, coming from point 3 of my last post. I stated that knowing the shop’s timezone at the time of the order was not “realistic”, but after thinking I realized It could be done, simply by saving the shop timezone along with the order.
So in the future, we’ll try to save all order dates in UTC, along with the shop timezone. This way, we can always trace back the order timezone using its UTC date + shop timezone at the time it was placed.
The only downside is that it only applies for future orders. For our previous data, I think we might have to reuse REST api to fetch the timezones.

This is all far too complicated, and once again would be solved very quickly if Shopify passed the local timezone along with the UTC date.

1 Like