Why moment js gives different milliseconds? - javascript

I getting error of different millisecond of same date using moment js.
I am getting data from server ('-2208988800000'). I converted the value in 'DD-MMM-YYYY'. Now I want again same millisecond, why I am getting different milliseconds of same date? Here is my code
http://plnkr.co/edit/1QoWLoFqkNAe2ebZ0V01?p=preview
I have two console x1 and x2. They are different, why?
var x = '-2208988800000'
var d = new Date(moment(new Date(parseInt(x)).toUTCString()).format('DD-MMM-YYYY'));
console.log(d)
var x2 = moment(new Date(d).toUTCString()).format('x');
console.log(x2)
// why x1 and x2 is different
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment.min.js"></script>
How can I get the same value?

You've got a terrible amount of manipulation back and forth between moment objects, date objects, and strings. It's unclear what you actually want to accomplish, but none of that should be necessary.
As to the result, the first call to the date constructor is getting the string value '31-Dec-1899', and thus you can reduce the example to:
var d = new Date('31-Dec-1899');
console.log(+d);
This will give different results depending on what browser you're running (because the implementation of parsing by the date object is implementation dependent when not in a standard format), and it will vary by time zone where the code is run (because it's assumed the value is in terms of local time).
For me, running in Chrome 70 on Windows 10, in the US Pacific time zone, this logs -2209046400000. You may get different results.
In general, don't do so much manipulation. Most functions you could want are built in to Moment. Any time you find yourself converting to strings and back to objects, or using the Date constructor, you're probably introducing bugs.

When you format the date to DD-MMM-YYYY you're losing hours and minutes, that's part of the reason
Try updating your code to
var d = new Date(moment(new Date(parseInt(x)).toUTCString()).format('DD-MMM-YYYY HH:mm:ss'));
and you will get a timestamp that is closer

Related

date.setHours() function does not fully set the time to zero

I am using the "MongoDB for VS Code" plugin in Visual Studio Code (v1.49.0) and am trying to reset the time of a Date object to 00:00:00:000 in the MongoDB Playground.
Here is the code:
var thisMonth = new Date();
thisMonth.setDate(1);
thisMonth.setHours(0, 0, 0, 0);
thisMonth;
However, the value output for thisMonth is:
2020-09-01T06:00:00.000Z
and not 2020-09-01T00:00:00.000Z as expected. This happens regardless of when the Date object is created. Does anyone else have experience or know why this might be happening?
Thank you.
MongoDB will always use UTC time (UTC-0 or Zulu/Zero time).
The hours you set are according to your local timezone, so in this case most likely North America (UTC-6). The result is given with a Z on the end indicating it is Zulu time (zero time).
To get the offset on your local machine you can use thisMonth.getTimezoneOffset();
To set the time to UTC time you use thisMonth.setUTCHours(0);
You will see that when setting the time to UTC time 0 you will actually get the 0 result you are looking for.
MongoDB does not have an understanding of timezones.
This is not related to MongoDB but normal JavaScript behaviour. See Date#setHours():
The setHours() method sets the hours for a specified date according to local time [...].
MongoDB transforms dates into their UTC representation before storing them. And you (or your server) seem to be located in a -6:00 time zone. The actual moment in time is correct, you are just seeing a representation that might not be what you expected.

new Date() returns relative time and not UTC time

When I go to my browser development tools and write new Date() in the console, it gives me the following
Mon Dec 18 2017 17:11:29 GMT+0200
I thought it suppose to return the UTC time.
The issue is that I have a server on AWS which writes UTC time to a DB. it writes it as a string and on the client side I do the following
const updatedMilliAgo = new Date() - new Date(timeStrFromDb);
For some reason the diff is two hours even due I check it right after the write in the server.
What am I doing wrong here?
When you use new Date(), you are constructing a Date object using the current value of the system clock where the code is executing. The Date object internally stores only a number of milliseconds since 1970-01-01T00:00:00Z (without consideration of leap seconds). In other words, Date objects are always representing the UTC time.
However - there are many functions and parameters on the Date object that work in local time. For example, when you call .toString() on a Date object, the computer's local time zone is applied to the internal UTC-based value, in order to generate a string that reflects local time.
In the case of console.log - a standard object like Date cannot be directly logged. Instead, most implementations will log a string value. How that value is created is entirely implementation specific, and not defined by the ECMAScript specification. Many implementations will return the same local-time based value that .toString() returns. Some (FireFox, for example) will return the same UTC based value that .toISOString() returns. It would be reasonable for an implementation to return the actual number of milliseconds stored (.valueOf()), or some other representation. If you need consistency, don't just log the Date object. Instead, log the output of one of its functions that returns a string or a number.
You also asked about subtracting two date objects. That will implicitly call .valueOf() on each object, subtracting their UTC-based internal values and giving you the number of milliseconds between them. The most likely problem you are encountering is with how you construct the second Date object. You didn't give an example of what timeStrFromDb consists of, but understand that how that string is formatted directly relates to how the Date object is constructed. If you aren't using a standardized format, or you aren't clear on whether the value is based on UTC or a specific offset from UTC, your string may be parsed differently than you expect.
Try to use
var d = new Date();
var n = d.toUTCString();
console.log(n)
I am late, but I didn't find the answer and I had to fight for hours vs the code... finally my solution was as simple as that:
TimeZone timeZone = TimeZone.getTimeZone(ZoneId.of("UTC"));
timeZone.setDefault(timeZone);
When you set the default timezone, all dates you create will be in that ZoneId that you specify.
I hope to help to someone.

String to Date conversion in JavaScript

My service is returning this as date 7/14/2016 2:40 AM +00:00. How can I convert this to UTC in JS?
Tried:
new Date("7/14/2016 2:40 AM +00:00").toISOString();
In database the date has been stored as UTC so when I will display the date I want to display as Local time.
There are many ways to parse a string to produce a Date object.
One way is with the Date object itself, either by passing a string to the constructor, or by using Date.parse. However, only the ISO8601 formats are required in the ECMAScript specification. Any other input is implementation specific, and may or may not be recognized by the different JavaScript runtimes. With web browsers in particular, there are many differences in supported formats across browsers.
Additionally, the locale of the environment plays a factor in how the values are parsed. How should 1/2/2016 be parsed? January 2nd, or February 1st? You showed an example of 7/14/2016, which would be invalid input if ran in the UK (for example), where the date format is DD/MM/YYYY.
You can write custom code to split the string up into its parts, parse each part individually, and compose a result. The main problem with this approach is that the code tends to be rigid, and sometimes fragile. It should be well tested, and many edge cases need to be considered.
You can use a library, which is by far the easiest and most flexible approach (IMHO). With a good library, you can take comfort in the shared experiences of others, and in the unit tests that are (hopefully) part of the library you choose. Of course, using a library comes with several tradeoffs including increased file size, and relinquishing some degree of control. You should evaluate these tradeoffs carefully.
There are many date libraries available for JavaScript. The most popular is probably moment.js, though there are others to choose from, and some larger frameworks sometimes have similar functionality already included.
Here is an example using moment.js:
var i = "7/14/2016 2:40 AM +00:00";
var f = "M/D/YYYY h:mm A Z";
var m = moment(i, f);
var o = m.format(f); // will be in the local time, in the same format as the input
var d = m.toDate(); // if you really want a Date object
Assuming you can guarantee that format for all dates, the following code will suffice:
const datetime = '7/14/2016 2:40 PM +00:00'; // this is what your service returns
const pieces = datetime.split(/[/: ]/);
if (pieces[3] == 12) pieces[3] = 0; // fixes edge case for 12 AM/PM
const hours = pieces[5] === 'PM' ? Number(pieces[3]) + 12 : pieces[3];
const d = new Date(Date.UTC(pieces[2], pieces[0] - 1, pieces[1], hours, pieces[4]));
console.log(datetime); // prints "7/14/2016 2:40 PM +00:00"
console.log(d); // prints Date 2016-07-14T14:40:00.000Z
EDIT: There's a couple edge cases with this not handled correctly, namely 12 AM/PM, etc. but those can easily be worked around as well.
EDIT2: Accounted for that edge case.
EDIT3: As a comment stated, this will only work for UTC times. If the string you're receiving can have any offset, this will not work.
var str = "7\/15\/2016 1:00 AM +00:00".replace("+00:00","UTC");
console.log(new Date(str).toISOString()); // 2016-07-15T01:00:00.000Z

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)

Add timestamp offset to local timestamp in javascript

Suppose I am in Sri Lanka (offset +5.30). I want to schedule a Meeting at 8.00 AM in American local time(offset -10.00) while I am staying in Sri Lanka.
I want to create my timestamp by adding offset of America to my local timestamp.
Have any one has idea of how to do that in javascript without using moment timezone.
What I have done is,
var localTimestamp = new Date('2015-02-27 14:59').getTime();
var offset = parseInt('-10.00')*60*60;
var timestamp = (localTimestamp/1000) + offset;
Above gives wrong result after converting back to local time.
There are a couple of issues there.
You're relying on undocumented behavior here:
var localTimestamp = new Date('2015-02-27 14:59').getTime();
That string format is not defined in the specification. V8 will parse it (as of this writing), but you have no guarantees about whether it parses it in local time or UTC or what, because (again) it's undefined. To create a date/time in a defined way, you could use the date/time format in the spec, but sadly they got that format wrong in ES5 and are having to fix it in ES6: In ES5, the absense of the "Z" at the end was defined as meaning UTC, but that's at odds with the ISO-8601 standard it was based on, and means you don't have a way to say "local time." Since ES6 will fix this, some engines have already changed it; whether your version of V8 has depends on the version number. So you're probably better off using the multi-argument date constructor:
var localTimestamp = new Date(2015, 1, 27, 14, 59).getTime();
// Remember that months start at 0 -^
There's zero reason for parseInt('-10.00'); just use -10.
Here you're dividing by 1000:
var timestamp = (localTimestamp/1000) + offset;
But then you say
Above gives wrong result after converting back to local time.
You need to multiply again when going back:
var newDate = new Date(timestamp * 1000);
Then you need to be careful about how you use the resulting Date, because it still works in what it considers local time. But if you're converting it to a string, etc., you could use it.

Categories