How to compare timespan in javascript after timezone conversion using moment js - javascript

I've a list of timespan(object list actually), like 2:00, 15:00, 18:00 etc, it is in utc.
Now i want to convert this time slot back to CST and then sort it, as i want my time sorted in cst.
For timezone conversion i needed temporary date. so i choose current utc date by
moment.utc(mytimespan). and performed the timezone conversion by .tz("CST").
So list is converted to 20:00,9:00, 12:00
Here please note that i got 20:00 in first place instead of last place in the list.
This is due to date part of moment which went in back date.
All here i want is my timespan in sorted form without any effect of date.
please me to find a way to do it without string conversion!
Thanks
Update
my currently working code using string conversion
TimeSpanDetails.sort(function compare(a, b) {
return moment(moment.utc(a.startTime).tz("CST").format("HH:mm"),"HH:mm").isAfter(moment(moment.utc(b.startTime).tz("CST").format("HH:mm"),"HH:mm")) ? 1 : -1;
});
Now i want to do it without string conversion using format

A few things:
A "time span" usually refers to a duration of time, not a time-of-day. These are two very different concepts that are sometimes confused. Consider:
A timespan of 99 hours is perfectly valid, but "99:00" is nonsensical as a time-of-day.
Due to daylight saving time and other time zone transitions, a timespan can't necessarily be thought of as "time since midnight" because midnight may or may not exist, or some other hour of the day may be absent or repeated.
Time spans can be negative in some programing languages, usually representing a period before a given point in time.
The tz function in Moment.js takes IANA time zone names. You should not use CT or CST, but rather America/Chicago, for example. However, time zones are completely unrelated to time spans, so you should not be applying them at all. You do not need moment-timezone.
Moment represents time spans in Duration objects. You can parse them from strings like so:
var d = moment.duration('99:00');
Duration objects convert numerically to milliseconds, so they are comparable like so:
var a = moment.duration('00:00');
var b = moment.duration('01:00');
var c = a < b; //=> true
Moment does not have a strongly typed object for a time-of-day, but you can use Moment in UTC mode so that it does not have DST transitions, and then just let it use the current day. HOWEVER:
This would assume that all time-of-day values you have should be evaluated on the same date.
This may or may not be the case.
Consider that if all you have is time-of-day and don't know what dates they're from, then the values ['23:00', '00:00'] may be sorted already and only one hour apart, or perhaps they're out of sequence and they are 23 hours apart.

Related

Having troubles with converting time in iso using java

I use the below code to format date time in iso format using java (I'm reducing 1 min from current time) and get the output as this "2016-03-17T11:38:21.xxxZ" < x represent some numbers> i want this to compare with the time which have mentioned in the DB.
Person who build that data insert query, he used javascript to get the time and format it in iso.
Date inside the DB is looks like this "2016-03-17T06:09:21.530Z" and its actual time is "11:39:21 GMT+0530 (India Standard Time)" which is similar to my current time but I'm comparing these two dates as string. and get 1min early data from DB.In that case i can't get an out put because as strings these two aren't match. can anybody recomand a solusion ?
I use OrientDB
Java Code
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
Calendar date = Calendar.getInstance();
long t = date.getTimeInMillis();
date.setTimeInMillis(t);
date.set(Calendar.MINUTE, date.get(Calendar.MINUTE) - 1);
String time1minEarly = df.format(date.getTime());
Using Calendar.set() and Calendar.get() does not modify the date in a way you intend:
This will modify the minutes field in your case. So subtracting "1" will reduce the minute but not give a viable date for cases where minute initially is zero.
You may just subtract a minutes of milliseconds from your "t" variable to get a true minute offset.
And for ease of use you might also consider following advise from #Prashant and using LocalDateTime class from joda library.
Thanks Everybody for your support.
I figure out How to do this. it's pretty easy. Both #rpy and #Prashant are correct. Calendar is not suitable for solve my issue. Also LocalDateTime too. but it did help me to figure out the correct way.
#rpy and #Prashant they both did miss one thing that the javascript time represent the UTC time. that's the issue. (it's 5.5 hours behind compared to my location) so, I figure out this below code. it did what i wanted to do.
It's pretty easy. all you have to do is provide your zone id.
(You can get Zone id using this code : go to the link - http://www.javadb.com/list-possible-timezones-or-zoneids-in-java/)
Also you can choose so many formats by changing "DateTimeFormatter" value.
ZoneId UTCzoneId = ZoneId.of("UTC");
ZonedDateTime time1minEarly = ZonedDateTime.now(UTCzoneId).minusMinutes(1);
String UTCtime1minerly = time1minEarly.format(DateTimeFormatter.ISO_INSTANT);
Out put is similar to this : "2016-03-17T10:39:21.530Z"
(- UTC time at that time : 2016-03-17T10:40:21.530Z)

momentjs days difference between two GMT dates

I'm trying to get difference of days between two GMT dates using moment
but I couldn't find it.
I'm on IST(+05:30) and I have some GMT dates(-05:00) in db,
I tried using following command
temp2.diff(temp1, "days")
here is a screenshot of all the commands tried in console
there we can clears see that dates are different and still shows the difference is 0
here is how I'm initializing moment objects of 'America/New_York'
var temp1 = moment.tz(new Date('Mon Jan 25 2016 22:00:00 GMT-0600'), 'America/New_York');
var temp2 = moment.tz(new Date('Tue Jan 26 2016 00:00:00 GMT-0600'), 'America/New_York');
any help appreaciated, thanks.
Well, there is less than 24 hours difference between those dates, so it's correct. The documentation says:
By default, moment#diff will return number rounded down. If you want the floating point number, pass true as the third argument.
> temp2.diff(temp1, "days", true)
0.08333333333333333
If you don't care about the hours at all, set them to 0 before you do the comparison
> temp2.hours(0).diff(temp1.hours(0), "days")
1
A few things:
You say that you are retrieving these values from a database, but then you show us loading them via the Date constructor from a string value. If you are really storing a string in your database, especially in that particular format, then you have much larger problems than the one you asked about! Please show us precisely how you load the values from your database to begin with.
You shouldn't rely on the Date object for parsing, especially when you are already using moment, which has much better parsing routines of its own.
You said these values where in America/New_York, but then you show an offset of -0600. That's never used in that time zone. The offset for the value you showed would be -0500.
You also said "I have some GMT dates(-05:00)" - which doesn't make any sense. GMT is +00:00. GMT-0500 means "5 hours behind GMT". Thus, you no longer have a "GMT date".
Be aware that the JavaScript Date object can only use the time zone of where the code is running. You cannot run it in any other time zone.
While Felix is correct in how you can show decimals with the diff function, you should realize that diff is giving you the actual elapsed time between the two moments in time you asked about. However, you seem to be wanting to know the total number of calendar days separating the two days that the moments fall into within the named time zone. To do that, you'd need to ignore the time portion. Using startOf('day') is an easy way to do that. Consider:
var a = moment.parseZone("2016-01-25T23:00:00-05:00");
var b = moment.parseZone("2016-01-26T01:00:00-05:00");
b.diff(a, 'days', true) // 0.08333333333333333 (not what you want)
b.startOf('day').diff(a.startOf('day'), 'days') // 1 (that's better!)
moment(b).startOf('day').diff(moment(a).startOf('day'),'days') // 1 (best approach)
Note a few things with this code:
The code in the last line is the best approach, as it leaves the original values of a and b alone. Otherwise, they would be modified. (Moments are mutable.)
You seem to already have the correct local time and offset, and thus there's no need to use moment-timezone's tz function. You can just use parseZone. Of course if this was just a side effect of your example, then you could still use moment-timezone, but I'd strongly recommend against using the Date constructor still.

Moment.js local relative time

I have dates in my database set to Europe/London time. I am using Moment.js to show relative time e.g. "3 minutes ago". This works fine for me as I am in the same timezone, but for example, someone who is PST timezone would see "in 8 hours". How can I fix this?
My current code is like this:
$('time').text( moment( '2016-01-22 18:00:00' ).fromNow() );
To echo Jon's answer, moment's relative time functionality is strictly UTC based, so the behavior you describe won't actually happen, unless you are interpreting the original timestamp in local time.
It's hard to say if you're doing that or not, as you didn't give a sample value of the input string.
If your times are indeed UTC based, but that's not reflected in the input string, then use moment.utc instead of just moment.
And no, London is not the same as UTC.
I believe that the best approach is to store the date in UTC and then convert this to the local time zone for display. Note that this is not necessarily the same as London time because UTC does away with daylight savings time nonsense. You can do everything that you need with the date class provided the time stamp stored in the database does not have to deal with the vagaries of time zone and DST. The date class maintains its own epoch internally as milliseconds elapsed since midnight 1 January 1970 UTC. You can evaluate the difference between two Date objects as follows:
var agora = Date.now();
var stored = ... // the date that was stored in your database
var diff_msec = agora.getTime() - stored.getTime();
Knowing that the difference and that its units are milliseconds, you can convert the difference to whatever units are best for presentation.

Reliable way to convert javascript timestamp into a date tuple

I want to convert javascript time stamps to erlang dates. I am using the qdate library to help me do that since it also provides functions for date arithmetic.
Calling it's to_date function first before midnight and then after midnight results in time displacement of 24 hrs. For example:-
qdate:to_date(Timestamp div 1000).
%% {2015,5,2} before midnight
qdate:to_date(After_midnight_Timestamp div 1000)
%%{2015,5,2} after midnight should be 3 instead of 2
I googled around a bit and found this in the erlang calender docs
The time functions local_time/0 and universal_time/0 provided in this module both return date and time. The reason for this is that separate functions for date and time may result in a date/time combination which is displaced by 24 hours. This happens if one of the functions is called before midnight, and the other after midnight. This problem also applies to the Erlang BIFs date/0 and time/0, and their use is strongly discouraged if a reliable date/time stamp is required.
I am having trouble understanding this. Which one of the functions from local_time/0 and universal_time/0 always gives the correct results? By correct I mean I want the right date to be shown after midnight. The resolution of the time is only {y,m,d}. Don't care for hours, minutes and seconds or anything finer than that.
So how do I reliably convert a javascript timestamp to a date in erlang?
Looks like it was just a timezone issue :) Since I was working with javascript timestamps the default timezone of the javscript time stamp is my localtimzone which is "IST". Now internally when qdate sees an integer in qdate:to_date(Timestamp). it automatically selects a UTC timezone for it. Relevant code on line 256:-
raw_to_date(Unixtime) when is_integer(Unixtime) ->
unixtime_to_date(Unixtime);
%% other clauses
and on line 654
unixtime_to_now(T) when is_integer(T) ->
MegaSec = floor(T/1000000),
Secs = T - MegaSec*1000000,
{MegaSec,Secs,0}.
unixtime_to_date(T) ->
Now = unixtime_to_now(T),
calendar:now_to_datetime(Now).
The final clue comes from the erlang calendar documentation itself
now_to_datetime(Now) -> datetime1970()
Types: Now = erlang:timestamp()
This function returns Universal Coordinated Time (UTC) converted from the return value from erlang:now().
So the solution to this problem was to simply supply an IST string with qdate:to_date() like so:-
qdate:to_date("IST",Timestamp div 1000)
and it started returning correct dates. I wasn't sure of the solution so I ran a test with qdate:to_date(erlang:now()) and the value returned was exactly 5:30 hrs behind my clock time. So it seems that supplying the timezone string works :)

Get local time representation of Date in arbitrary timezone in arbitrary day - considering Daylight Savings Time

For sure, there is a lot of questions about Date objects and timezones but many of them are about converting the current time to another timezone, and others are not very clear about what they want to do.
I want to display the day, hour, minute etc. in an arbitrary timezone, in an arbitrary day. For example, I would like a function f(t, s) that:
given the timestamp 1357041600 (which is 2013/1/1 12:00:00 UTC) and the string "America/Los Angeles", would satisfy the comparison below:
f(1357041600, "America/Los Angeles") == "2013/01/01 04:00:00"
given the timestamp 1372680000 (2013/07/01 12:00:00 UTC), would satisfy the comparison below:
f(1357041600, "America/Los Angeles") == "2013/07/01 05:00:00"
will always behave this way even if the timezone in the browser is, let us say "Europe/London" or "America/São Paulo".
will always behave this way even if the time in the browser is, let us say 2014/02/05 19:32, or 2002/08/04 07:12; and
as a final restriction, will not request anything from the server side (because I'm almost doing it myself :) )
Is it even possible?
given the timestamp 1357041600 (which is 2013/1/1 12:00:00 UTC)
That appears to be seconds since the UNIX epoch (1970-01-01T00:00:00Z). Javascript uses the same epoch, but in milliseconds so to create a suitable date object:
var d = new Date(timestamp * 1000);
That will create a Date object with a suitable time value. You then need to determine the time zone offset using something like the IANA time zone database. That can be applied to the Date object using UTC methods. E.g. resolve the offset to minutes, then use:
d.setUTCMinutes(d.getUTCMinutes() + offset)
UTC methods can then be used to get the adjusted date and time values to create a string in whatever format you require:
var dateString = d.getUTCFullYear() + '/' + pad(d.getUTCMonth() + 1) + '/' ...
where pad is a function to add a leading zero to single digit values. Using UTC methods avoids any impact of local time zone offsets and daylight saving variances.
There are also libraries like timezone.js that can be used to determine the offset, however I have not used them so no endorsement is implied.
For JavaScript runtime environments that support the ECMAScript Internationalization API, and adhere to its recommendation of supporting the IANA time zone database, you can simply do this:
new Date(1357041600000).toLocaleString("en-US", {timeZone: "America/Los_Angeles"})
For other environments, a library is required. There are several listed here.

Categories