Moment js Use localtime for Fromnow() using Java Script - javascript

I am trying to find time ago in my html page, but the time considered for calculating is Greenwich meridian time.
I am currently trying
moment.utc(date).fromNow();
I tried to get time in my local zone using .tz('Asia/Kolkata') and tried:
moment.utc(date).from(moment(new Date()).tz('Asia/kolkata').format('llll'));
This still takes Greenwich meridian time to calculate.
EDIT
'date' is sent by node js server in a JSON There as well date is calculated using var date = moment(new Date()).tz('Asia/kolkata').format('llll').
For Me localtime is 'Asia/Kolkota'

I think the issue is you're trying to get momentJs to interpret a datetime string that isnt in a format that it can recognise (by using .format('llll')).
If you're trying to get the difference in time between the UTC of a given date, and the current Asia\Kolkata time. You're best to try something like:
// get "now" in Asia Kolkata and format into a string that Moment will understand
var dateFromServer = moment(new Date()).tz('Asia/kolkata').format('YYYY-MM-DD HH:mm:ss');
// to see a much different time try:
//var dateFromServer = moment('2016-12-31 15:00:00').tz('Asia/kolkata').format('YYYY-MM-DD HH:mm:ss');
// on client get "now" in Asia Kolkata
var nowInKolkata = moment().tz('Asia/kolkata');
// output string from "server"
dateOutput.innerHTML = 'date from "server": ' + dateFromServer;
// output difference between time "now" in Asia Kolkata, and the UTC version of the server date
result.innerHTML = nowInKolkata.from(moment.utc(dateFromServer));
JSFIDDLE

Related

Calculate duration between momentjs timestamps in UTC

I am having a hard time to calculate the duration (difference in time) of two timestamps.
There is a timestamp I receive from the server in the following format:
start # => "2017-05-31 06:30:10 UTC"
(This is basically rubys DateTime.now.utc)
I want to see how many hours have passed since then until as of right now.
The calculation happens in the angularjs frontend only.
I tried the following:
var start = moment("2017-05-31 06:30:10 UTC", "YYYY-MM-DD HH:mm:ss Z").utc();
var now = moment.utc();
var duration = moment.duration(now.diff(start));
console.log(duration.asHours()); #=> 2 hours even though the point in time was just a couple of minutes ago.
Unfortunately this would always use my devices local time and produce a time that's a few hours off the actual time.
So my approach was to either convert all times to UTC and let momentjs handle all this.
What am I missing?
Since your input is UTC you can use moment.utc method.
By default, moment parses and displays in local time.
If you want to parse or display a moment in UTC, you can use moment.utc() instead of moment().
Here a live example:
var start = moment.utc("2017-05-31 06:30:10 UTC", "YYYY-MM-DD HH:mm:ss Z");
var now = moment.utc();
var duration = moment.duration(now.diff(start));
console.log(duration.asHours());
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script>
In your code sample, you are parsing the input string as local date and then converting it to UTC (with utc() method).
See Local vs UTC vs Offset guide to get more info.

Return date and time in ("YYYY-MM-DD HH:mm") format when using moment.js (timezone)

I am using moment-timezone so I can convert from selected timezone to timezone of a client.
I wasn't able to implement it in a better way than this:
convertSelectedTimeZoneToClients() {
let timeZoneInfo = {
usersTimeZone: this.$rootScope.mtz.tz.guess(),
utcOffset: this.formData.timeZone.offset,
selectedDateTime: this.toJSONLocal(this.formData.sessionDate) + " " + this.formData.sessionTime
};
let utcTime = this.$rootScope.mtz.utc(timeZoneInfo.selectedDateTime).utcOffset(timeZoneInfo.utcOffset).format("YYYY-MM-DD HH:mm");
let convertedTime = this.$rootScope.mtz.tz(utcTime, timeZoneInfo.usersTimeZone).format("Z");
return convertedTime;
}
So basically I am using usersTimeZone: this.$rootScope.mtz.tz.guess(), guess() function to find out timezone from the browser.
Then I get values from datetime picker and dropdown and convert them to UTC value by using utcOffset.
At the end I want to convert that utc value to user timezone value.
I get object like this:
_d represent correct value after conversion. I have tried adding bunch of different .format() paterns on convertedTime variable, but I am not able to retrive time in this format: "YYYY-MM-DD HH:mm". I guess it works differentlly than when using .utcOffset() function.
Can anybody help me with this?
You don't need to guess the client time zone to convert to local time. Just use the local function.
For example:
moment.tz('2016-01-01 00:00', 'America/New_York').local().format('YYYY-MM-DD HH:mm')
For users located in the Pacific time zone, this converts from Eastern to Pacific and you get an output string of "2015-12-31 21:00". For users in other time zones, the output would be different, as expected.
You don't need to format to a string and re-parse it, or manually manipulate the UTC offset either. That is almost never warranted.

Need to read epoch time in certain timezone and then convert it to user timezone

I have 2 webapps, 1 of them on cloud is "master", to which I need to match dates in the 2nd webapp "child".
Master (1st webapp, cloud) is showing date in IST, Asia/Kolkata which it reads from sql machine sitting in EST timezone.
Child (2nd webapp) reads it's data from Elasticsearch where a java feeder picks up the sql data and pushes it to Elasticsearch as it is, without any conversion.
When I try to read this Elasticsearch data in my webapp (child)
...
{
"_index": "log_event_2016-05-05",
"_type": "log_event",
"_id": "65708004",
"_score": null,
"_source": {
"task_name": "kn_cvs_test",
"task_start_time": "2016-05-05T19:05:05.000-07:00",
"task_end_time": "2016-05-05T19:05:06.000-07:00",
"started_by": "Schedule \"10Minutes\"",
"log_datetime": 1462475106000,
"dw_insert_dt": "2016-05-05T16:40:54.000-07:00"
},
"sort": [
1462475106000
]
}, {
"_index": "log_event_2016-05-05",
"_type": "log_event",
"_id": "65708005",
"_score": null,
"_source": {
"task_name": "kn_cvs_test",
"task_start_time": "2016-05-05T18:55:08.000-07:00",
"task_end_time": "2016-05-05T18:55:11.000-07:00",
"started_by": "Schedule \"10Minutes\"",
"log_datetime": 1462474511000,
"dw_insert_dt": "2016-05-05T16:40:54.000-07:00"
},
"sort": [
1462474511000
]
}
...
the dates in my webapp and the cloud does not match. Please correct me if I am wrong. Since Sql is storing dates in EST, "America/New_York", Momentjs should 1st read the data = 1462475106000 in EST and then apply the user timezone which is IST, "Asia/Kolkata". Is this correct?
//Timestamp column in table
//data = 1462475106000
$scope.getMeData = function(data) {
var dFormat = "YYYY-MM-DD hh:mm:ss A";
moment.tz.setDefault("America/New_York");
return moment.tz(data, "Asia/Kolkata").format(dFormat);
}
Note: 1462475106000 is the 1st entry in both table
I am putting up a plunker here.
Please help me figure out what could be going wrong and how can I match dates in both the webapps (taking cloud as reference).
Update
Java feeder runs a sql query to fetch all the needed columns. Here is how log_datetime is fetched. Is this the correct way to fetch?
(task_end_time - to_date('1-1-1970 00:00:00','MM-DD-YYYY HH24:Mi:SS'))*24*3600*1000 AS "log_datetime"
So I am assuming when it fetches data Daylight saving information is not considered and I am missing out this info too. So on UI side i'll check for isDST() and do a +5:00 hrs or +4:00 hrs depending on it, as date in sql is stored in America/New_York. Plunker with UI fix
There's only one Epoch time anywhere at a time. It's an absolute value.
A value that approximates the number of seconds that have elapsed since the Epoch. A Coordinated Universal Time name (specified in terms of seconds (tm_sec), minutes (tm_min), hours (tm_hour), days since January 1 of the year (tm_yday), and calendar year minus 1900 (tm_year)) is related to a time represented as seconds since the Epoch, according to the expression below.
Ref http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_15
Epoch time is measured from the 01-01-1970 00:00:00 UTC. That's an absolute instant in time, it's not relative to timezone as the timezone UTC is in definition of the epoch.
Whenever you see a number for a date such as your example 1462475106000, it should be assumed to be in UTC/GMT. It's not a timezone specific value. Since the time is Unix based number, by epoch definition it is time passed since epoch (in UTC), making it absolute time.
(01-01-1970 00:00:00 UTC)(epoch) + 1462475106000 = Time in UTC
A date in string is a different matter entirely. It should include the timezone offset with the date part. Date part would be considered to be timezone specific value. Adding timezone offset to it would convert it to absolute value in UTC. Without timezone information a string date has no absolute value (Point in time).
2016-05-05T18:55:08.000-07:00 = (2016-05-05T18:55:08.000) + (07:00 hrs) UTC
or
date + timezone offset = date - offset hrs UTC
Databases don't store dates in any timzzone. They store absolute Unix time value. Timezone setting in databases are set so that the output of the query in string is shown in that timezone format. This setting only specifies the output date format not the value. Since the value is absolute it's same timezone independent.
This setting also helps database in determining the timezone of the date value that a user inserts if he misses the timezone offset. If the user tries to insert a string in date column without timezone database would try to default the string to database timezone setting.
So 1462475106000 is a value in UTC as it's Unix time. It's not in EST.
If you need date to be in EST then use the date in string format not in number format as number format is always UTC.
moment.tz.setDefault("America/New_York");//sets the output date format in EST
Above code will have no effect as it's overwritten by moment.tz(data, "Asia/Kolkata")
Now considering the first entry in the first screenshot.
2016-05-06T04:35:06.000+5:30 (IST) = 2016-05-05T11:05:06.000-00:00 (UTC)
Comparing it with the second screenshot, since the time difference between the two is 4 hours, second one should be in +01:30 timezone, if they both are the same values in absolute time.
2016-05-06T12:35:06.000+1:30 = 2016-05-05T11:05:06.000-00:00 (UTC)
However in the child the value is
2016-05-05T19:05:06.000-07:00 = 2016-05-06T02:05:06.000-00:00 (UTC)
Which is not the same value as both above. Interesting fact is that only date part in the child 2016-05-05T19:05:06.000 when added IST offset +05:30would become the date part in second screenshot.
2016-05-06T12:35:06.00 - 2016-05-05T19:05:06.000 = 5:30 (IST offset)
Leaving that aside your Java feeder code to ElasticSearch is probably culprit here.
It's not writing the correct date-timezone combination to ElasticSearch. Try using the overloaded method getDate()
getDate(int columnIndex, Calendar cal)
in JDBC.
Sometimes JDBC driver misses timezone information, causing the date to be stored in default database timezone, using Calendar would cure that.
Same goes for writing dates as well.
void setDate(int parameterIndex, Date x, Calendar cal) throws SQLException
You just need to convert dates from America/New York to Asia/Kolkata (Asia/Calcutta)?
var newYork = moment.tz("date-from-database", "America/New_York");
var calcutta = newYork.clone().tz("Asia/Calcutta");
Example
var newYork = moment.tz("2016-05-06 12:00:00", "America/New_York");
var losAngeles = newYork.clone().tz("America/Los_Angeles");
var london = newYork.clone().tz("Europe/London");
var Kolkata = newYork.clone().tz("Asia/Kolkata");
var dFormat = "YYYY-MM-DD hh:mm:ss A";
console.log(newYork.format(dFormat),losAngeles.format(dFormat),london.format(dFormat),Kolkata.format(dFormat));
Fiddle

Why does Date#getHours() return hour + 1?

This is my code:
var feedDataTimestamp = new Date("2014-01-14T00:04:40+0000").getTime();
var parsedDate = new Date(+feedDataTimestamp);
alert(parsedDate.getHours());
but it should print 0, not 1: time is 00:04:40
Because you (according to your Stackoverflow profile) are in Italy, so your time zone is UTC+1.
The time stamp you are inputting is UTC+0.
parsedDate will be in local time.
Use the getUTCHours() method if you want to get UTC time instead of local time.
You set the timezone in the parsed string as +0000 so you seem to want the hours in UTC, use
alert(parsedDate.getUTCHours())

How do you preserve a JavaScript date's time zone from browser to server, and back?

For example, using a date and time control, the user selects a date and time, such that the string representation is the following:
"6-25-2012 12:00:00 PM"
It so happens that this user is in the EST time zone. The string is passed to the server, which translates it into a .NET DateTime object, and then stores it in SQL Server in a datetime column.
When the date is returned later to the browser, it needs to be converted back into a date, however when the above string is fed into a date it is losing 4 hours of time. I believe this is because when not specifying a timezone while creating a JavaScript date, it defaults to local time, and since EST is -400 from GMT, it subtracts 4 hours from 12pm, even though that 12pm was meant to be specified as EST when the user selected it on a machine in the EST time zone.
Clearly something needs to be added to the original datetime string before its passed to the server to be persisted. What is the recommended way of doing this?
Don't rely on JavaScript's Date constructor to parse a string. The behavior and supported formats vary wildly per browser and locale. Here are just some of the default behaviors if you use the Date object directly.
If you must come from a string, try using a standardized format such as ISO8601. The date you gave in that format would be "2012-06-25T12:00:00". The easiest way to work with these in JavaScript is with moment.js.
Also, be careful about what you are actually meaning to represent. Right now, you are passing a local date/time, saving a local/date/time, and returning a local date/time. Along the way, the idea of what is "local" could change.
In many cases, the date/time is intended to represent an exact moment in time. To make that work, you need to convert from the local time entered to UTC on the client. Send UTC to your server, and store it. Later, retrieve UTC and send it back to your client, process it as UTC and convert back to local time. You can do all of this easily with moment.js:
// I'll assume these are the inputs you have. Adjust accordingly.
var dateString = "6-25-2012";
var timeString = "12:00:00 PM";
// Construct a moment in the default local time zone, using a specific format.
var m = moment(dateString + " " + timeString, "M-D-YYYY h:mm:ss A");
// Get the value in UTC as an ISO8601 formatted string
var utc = m.toISOString(); // output: "2012-06-25T19:00:00.000Z"
On the server in .Net:
var dt = DateTime.Parse("2012-06-25T19:00:00.000Z", // from the input variable
CultureInfo.InvariantCulture, // recommended for ISO
DateTimeStyles.RoundtripKind) // honor the Z for UTC kind
Store that in the database. Later retrieve it and send it back:
// when you pull it from your database, set it to UTC kind
var dt = DateTime.SpecifyKind((DateTime)reader["yourfield"], DateTimeKind.Utc);
// send it back in ISO format:
var s = dt.ToString("o"); // "o" is the ISO8601 "round-trip" pattern.
Pass it back to the javascript in moment.js:
// construct a moment:
var m = moment("2012-06-25T19:00:00.000Z"); // use the value from the server
// display it in this user's local time zone, in whatever format you want
var s = m.format("LLL"); // "June 25 2012 12:00 PM"
// or if you need a Date object
var dt = m.toDate();
See - that was easy, and you didn't need to get into anything fancy with time zones.
Here, I think this is what you are looking for:
How to ignore user's time zone and force Date() use specific time zone
It seems to me that you can do something like this:
var date = new Date("6-25-2012 12:00:00 PM");
var offset = date.getTimezoneOffset(); // returns offset from GMT in minutes
// to convert the minutes to milliseconds
offset *= 60000;
// the js primitive value is unix time in milliseconds so this retrieves the
// unix time in milliseconds and adds our offset.
// Now we can put this all back in a date object
date = new Date(date.valueOf() + offset);
// to get back your sting you can maybe now do something like this:
var dateString = date.toLocaleString().replace(/\//g,'-').replace(',','');
Blame the JSON.Stringfy()... and do:
x = (your_date);
x.setHours(x.getHours() - x.getTimezoneOffset() / 60);
I am using a filter before sending the date to the server:
vm.dateFormat = 'yyyy-MM-dd';
dateToSendToServer = $filter('date')(dateFromTheJavaScript, vm.dateFormat);

Categories

Resources