Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to handle differing server and client times #122

Closed
jshah4517 opened this issue Mar 23, 2017 · 23 comments
Closed

How to handle differing server and client times #122

jshah4517 opened this issue Mar 23, 2017 · 23 comments

Comments

@jshah4517
Copy link

jshah4517 commented Mar 23, 2017

What's the best way of handling when the server and client times differ? For example, if the clients clock is 5 mins behind, it would show 'in 5 minutes' instead of 'just now' which looks wrong.

I tried to enter a relative date like timeago('2016-06-10 12:12:12'), but after doing so it seems that the real-time updating no longer works. I believe this is because the diffSec function uses that date as the base to compare against rather than new Date().

// calculate the diff second between date to be formated an now date.
function diffSec(date, nowDate) {
  nowDate = nowDate ? toDate(nowDate) : new Date();
  return (nowDate - toDate(date)) / 1000;
}

If this isn't possible currently, perhaps if a relative date is entered, it should instead store an offset against new Date() and use that when working out the difference?

@hustcc
Copy link
Owner

hustcc commented Mar 24, 2017

That is realy a problem, the relative date can not solve the realtime render.

May be a time differ can solve it, but eveny client has different time differ.

@likerRr
Copy link
Collaborator

likerRr commented Mar 24, 2017

@jshah4517 if something is wrong with a client's time, it's his problem. The library shows relative diff to the clients time, not to UTC or GMT or something else.

As for ux you can show an alert to a client, that his clock is out of date and if the user doesn't fix it, the timers could work wrong. That's how it's done in JIRA.

@likerRr
Copy link
Collaborator

likerRr commented Mar 24, 2017

Ok, to solve the auto render problem you should return correct time from server, compare it with the client's time and add the difference to relative time which you use instantiating timeago. Will it help?

timeago('2016-06-10 12:12:12 + difference between server and client')

@jshah4517
Copy link
Author

jshah4517 commented Mar 24, 2017

I had a go at a solution which makes the use of a relative date real-time too, the changes are hopefully fairly minimal. It seems to work quite nicely.
jshah4517@029754a

What do you think? I would be happy to submit a PR if it would seem like a worthwhile addition.

Edit: I should just mention, I only aimed to get it working for this case and haven't considered that perhaps people might want to use the relative date option without real-time updates, but perhaps this could be added as a third parameter?

@likerRr
Copy link
Collaborator

likerRr commented Mar 24, 2017

@jshah4517 thank you for trying solve this issue 😄

I think that function diffSec should compare difference between it's args. But after your changes it seems like the functions calculates difference between time and offset, which is not very consistent. So probably we should think on it more.

And you are right. If we want this feature then the changes should work both for real-time and for format.

@hustcc what do you think?

@jshah4517
Copy link
Author

@likerRr Yes, you're right, especially if wanting to maintain how it currently works for relative dates.

I would probably add a new function offsetDate which works it out with the offset (set offset to 0 and enter relative date if not wanting real-time) and that gets fed in to the diffSec function.

I'll wait for @hustcc, but I'm happy to give it a go if it seems like a good suggestion.

@hustcc
Copy link
Owner

hustcc commented Mar 27, 2017

@likerRr @jshah4517
I have encountered this problem when I use timeago.js in other projects.

I think add one config namd offset is better then modify the function diffSec.

  1. Keep the construction method unchanged.
  2. Add one API setOffset(diff sec between server and client time, can be negative) on timeago instance, default is 0.
  3. Sum the offset with the result of function diffSec.

The above is what I'm thinking, how do you think? The name of var and API need to confirm.

@jshah4517
Copy link
Author

This works, but I think the offset could be calculated automatically. Would there ever be a need to have an offset which is different to what the difference between the relative date and client time is?

My thought was a boolean for the third param realtime, where it works out and stores the offset automatically based on the relative date. In terms of compatibility, I guess it would need to be true automatically if no relative date is entered, false by default otherwise. That would be my only hesitation with it, as it's potentially inconsistent, so maybe what you are proposing is safer?

@likerRr
Copy link
Collaborator

likerRr commented Mar 27, 2017

It could be automatically calculated, but i think a manual value is more "user" friendly way.

Imagine the app that renders how much time until sale starts in some online shop for different countries. Here we need to set offset manually for each of the country.

So i think the solution proposed by @hustcc is well enought.

@jshah4517
Copy link
Author

OK I agree, that solution will be the most flexible. 👍

@hustcc would you like a PR? I might have time later this week.

@hustcc
Copy link
Owner

hustcc commented Mar 28, 2017

Waiting for your PR ^_^

@EvilJordan
Copy link

Aw, man. I got all excited someone else had solved this and then... no pull request :(

@aprilmintacpineda
Copy link

Please update the readme to include instructions as to how to use this feature.

@thedotedge
Copy link

No PR still? 😢

@Animalejourbano
Copy link

Is this already available or still an issue?

@EvilJordan
Copy link

I have this working, but it relies on both a server-side passing of data and a modification to how one calls timeAgo (by passing in an element ID, though one could easily modify the below for a class or multiple elements at once:

In the Javascript (and this is jQuery specific):

 function timeAgo(elementID) {
    $("#"+elementID).each(function() {
        var newDate = new Date();
        var newLastUpdateDate = new Date((newDate.getTime() - ($(this).data('now')*1000)) + $(this).data('lastupdate')*1000);
        var d = new Date(newLastUpdateDate),
            dformat = [(d.getMonth()+1).padLeft(),
                       d.getDate().padLeft(),
                       d.getFullYear()].join('-') +' ' +
                      [d.getHours().padLeft(),
                       d.getMinutes().padLeft(),
                       d.getSeconds().padLeft()].join(':')
        $(this).attr('datetime',dformat);
        timeago().render($(this));
    });
}

The server passes along a unix timestamp of the object you're looking to track's last updated date (lastUpdateTime), as well as the server's current time (now), also as a unix timestamp.

The element on the client side ends up looking like this:

<span class='lastUpdated'>last updated <span id='timeAgo' data-now='"+now+"' data-lastupdate='"+lastUpdateTime+"'></span></span>
<script>timeAgo("timeAgo");</script>

@hustcc
Copy link
Owner

hustcc commented Jun 11, 2018

You can design it into v4.0.0, code is on master.

I think timeago need a global configure for:

  • default locale
  • timezone
  • offset between server and client
  • ...

@hustcc hustcc closed this as completed Jun 11, 2018
@hustcc hustcc reopened this Jun 11, 2018
@sprlwrksAprilmintacpineda

@hustcc or maybe what we can do is provide it a timezoneFrom to timezoneTo. Better yet, we can have a configuration where timeago automatically converts to the browser's / device's default timezone from a particular timezone...

@ppetree
Copy link

ppetree commented Jun 13, 2018

Just remember, offset will change. If I activate the app on GMT-5 (NY) and fly to LA my GMT will now be -8.

Really what you want to do is to get the offset on init. If you need a parameter, it should be a flag to ignore the offset.

var d = new Date();
var n = d.getTimezoneOffset();

@nayfield
Copy link

nayfield commented Nov 4, 2018

What I'd be interested in (and might solve some of the other use cases) would be the functionality to set a flag that indicates "treat all dates as UTC".

(To be clear - I'm only concerned about timezone differences, not the out-of-sync client problem)

The best pattern here is for the server to provide all times in UTC - and allow the clients to handle the conversion from their local timezone. This solves ppetree's comment (once his device updates its timezone).

I'm assuming this already works out-of-the-box when times are expressed with a specific offset or Zulu from the server. However, my native time format is seconds since epoch which javascript interprets as being in the local timezone.

@hustcc
Copy link
Owner

hustcc commented Oct 12, 2019

this will be related to network, I think it will not be considered in this module. sorry~

@hustcc hustcc closed this as completed Oct 12, 2019
@frankiejarrett
Copy link

I had the same problem. The solution for me was just adding UTC to the datetime string:

// Given a client timezone of EDT (GMT -4:00) and local time of 12:00 (noon)
const utcTimeFromServer = '2020-06-01 13:02:15';

timeago.format(utcTimeFromServer); // in 1 hour (bad)
timeago.format(utcTimeFromServer + ' UTC'); // 3 hours ago (good)

@samvandamme
Copy link

FYI strftime('%Y-%m-%d %H:%M:%S %z') (ruby on rails) works too, results in 2024-10-15 13:37:13 +0000

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests