I got this problem when dealing with date time conversion. I have timestamp data from postgreSQL database with format like this one
"2011-04-04 19:27:39.92034"
In order to display it in highcharts, I have to convert it to date or time object. Without milliseconds, I easily convert it with Date.js
But milliseconds can't be handled with that library. I tried also with Date.parse but always got NaN.
Any solution for this problem? Thank you
JS built in Date class should be able to handle this, and getTime() can return milliseconds since start 1970 (UNIX time). Watch out for time zone issues though; the constructor may interpret the date/time as being local, but getTime()'s milliseconds since 1970 may be in UTC, baking in a conversion that is difficult to remove.
new Date("2011-04-04 19:27:39.92034").getTime()
1301941659920
Many ways to Rome. The given code will return '(datestr=) 2011-4-4 19:27:39.92'. Is that what you look for?
var darr = '2011-04-04 19:27:39.92034'.split('.')
, dat=new Date(darr[0])
, datestr = '';
dat.setMilliseconds(Math.round(darr[1]/1000));
datestr = [ [dat.getFullYear(),dat.getMonth()+1,dat.getDate()].join('-')
,' ',
[dat.getHours(),dat.getMinutes(),dat.getSeconds()].join(':')
,'.',
dat.getMilliseconds()
].join('');
Can't you just cut of the last 6 chars of that string? You might then round the miliseconds and eventually add a second to you time object.
This is simpler and in one line:
new Date('01/09/2015 06:16:14.123'.split(".")[0])
Related
I've got a form where I input an event that starts at a certain time. Let's say 9am.
To assign a date/time object I'm using MomentJs. The issue comes when displaying it in different time-zones.
In London will show up 9am as intended - in Kiev will show 11am.
How can I make MomentJS and the browser ignore which timezone is relevant for the user, and just displaying the time I'm giving?
Here's my code:
<p>
Start time:
{moment(event.startDate).format("HH:mm")}
</p>
Assuming you have stored the date as utc (which in this case you probably should have), you could use the following:
moment.utc(event.startDate).format("HH:mm")
Let me provide an alternative answer in Vanilla JavaScript. If you want to make it timezone 'neutral', you can first convert it to UTC using toISOString().
const current = new Date();
const utcCurrent = current.toISOString();
console.log(utcCurrent);
If you want to convert it to a specific timezone, such as London, you can use toLocaleString(). Do take note of the browser support for the timezone though.
const londonTime = new Date().toLocaleString('en-US', { timeZone: 'Europe/London' })
console.log(londonTime);
What you want is a normalized Datetime. This can get a little confusing since the concept of timezones is a rather arbitrary construct.
I like to think of Datetime values as "absolute" and "relative". An "absolute" Datetime is one that is true regardless of which timezone you're in. The most common example of these are UTC(+000) and UNIX Time (also known as Unix epoch, POSIX Time or Unix Timestampe).
UTC is pretty obvious. Its the current time at +000 timezone. UNIX time is a bit more interesting. It represents the number of seconds that have elapsed since January 1, 1970.
You should always store data, in both client and backend, as an "absolute" time. My preference is UNIX time since its represented as a single integer (nice and clean).
moment.js does this for you. When you instantiate your moment object, you can use:
var date = moment.utc(utcString)
or for Unix Time
var date = moment.unix(unixInt)
You can then use this object to display the date in any form you wish:
console.log(date.tz.("America/Toronto"))
The only way I could solve this is by removing the timezone and milliseconds info from the string. I used date-fns lib but I imagine moment will work the same way.
import { format } from 'date-fns'
const myDateTimeString = '2022-02-22T19:55:00.000+01:00'
const dateTimeWithoutTimezone = myDateTimeString.slice(0, 16) // <- 2022-02-22T19:55
format(new Date(dateTimeWithoutTimezone), 'HH:mm')
I wish to create a new Date in JS, but have it be cast as UTC time. For example, suppose castAsUTC() produces the following desired effect:
var x = new Date('2019-01-01T00:00:00') // In local time (PST)
castAsUTC(x).toISOString(); // => '2019-01-01T00:00:00Z'
// x.toISOString() gives us '2019-01-01T08:00:00Z', which is undesired
Currently, my function looks like this:
function castAsUTC(date) {
return new Date(x.toLocaleString() + '+00:00');
}
Is there a cleaner/nicer way of producing the same effect? Thanks in advance!
EDIT: To be more specific, I'm interested in transforming the date's timezone, without changing its actual value with as little arithmetic as possible. So calling .toISOString() will produce the same date as it is in local time.
I am currently using the moment-timezone library, but I can't seem to get the desired effect using that, either. I would definitely accept an answer that uses Moment.js
You can switch a Moment instance to UTC using the utc function. Then just use format to get whatever the specific output you want from it.
If indeed the string you have is like the one shown, then the easiest thing to do would be to append a Z to indicate UTC.
var input = '2019-01-01T00:00:00';
var date = new Date(input + 'Z');
var output = date.toISOString();
Or, if you would like to use Moment.js, then do this:
var input = '2019-01-01T00:00:00';
var m = moment.utc(input);
var output = m.format();
You do not need moment-timezone for this.
tl;dr;
You formatted the date wrong. Add the letter "Z" to the end of your date string and it will be treated as UTC.
var x = new Date('2019-01-01T00:00:00Z') // Jan 1, 2019 12 AM UTC
These formatting issues are easier to manage with a library like momentjs (utc and format functions) as described in other answers. If you want to use vanilla javascript, you'll need to subtract out the timezone offset before calling toISOString (see warnings in the longer answer below).
Details
Date in javascript deals with timezones in a somewhat counter intuitive way. Internally, the date is stored as the number of milliseconds since the Unix epoch (Jan 1, 1970). That's the number you get when you call getTime() and it's the number that's used for math and comparisons.
However - when you use the standard string formatting functions (toString, toTimeString, toDateString, etc) javascript automatically applies the timezone offset for the local computers timezone before formatting. In a browser, that means it will apply the offset for the end users computer, not the server. The toISOString and toUTCString functions will not apply the offset - they print the actual UTC value stored in the Date. This will probably still look "wrong" to you because it won't match the value you see in the console or when calling toString.
Here's where things really get interesting. You can create Date's in javascript by specifying the number of milliseconds since the Unix epoch using new Date(milliseconds) or by using a parser with either new Date(dateString). With the milliseconds method, there's no timezone to worry about - it's defined as UTC. The question is, with the parse method, how does javascript determine which timezone you intended? Before ES5 (released 2009) the answer was different depending on the browser! Post ES5, the answer depends on how you format the string! If you use a simplified version of ISO 8601 (with only the date, no time), javascript considers the date to be UTC. Otherwise, if you specify the time in ISO 8601 format, or you use a "human readable" format, it considers the date to be local timezone. Check out MDN for more.
Some examples. I've indicated for each if javascript treats it as a UTC or a local date. In UTC, the value would be Jan 1, 1970 at midnight. In local it depends on the timezone. For OP in pacfic time (UTC-8), the UTC value would be Jan 1, 1970 at 8 AM.
new Date(0) // UTC (milliseconds is always UTC)
new Date("1/1/1970"); // Local - (human readable string)
new Date("1970-1-1"); // Local (invalid ISO 8601 - missing leading zeros on the month and day)
new Date("1970-01-01"); // UTC (valid simplified ISO 8601)
new Date("1970-01-01T00:00"); // Local (valid ISO 8601 with time and no timezone)
new Date("1970-01-01T00:00Z"); // UTC (valid ISO 8601 with UTC specified)
You cannot change this behavior - but you can be pedantic about the formats you use to parse dates. In your case, the problem was you provided an ISO-8601 string with the time component but no timezone. Adding the letter "Z" to the end of your string, or removing the time would both work for you.
Or, always use a library like momentjs to avoid these complexities.
Vanilla JS Workaround
As discussed, the real issue here is knowing whether a date will be treated as local or UTC. You can't "cast" from local to UTC because all Date's are UTC already - it's just formatting. However, if you're sure a date was parsed as local and it should really be UTC, you can work around it by manually adjusting the timezone offset. This is referred to as "epoch shifting" (thanks #MattJohnson for the term!) and it's dangerous. You actually create a brand new Date that refers to a different point in time! If you use it in other parts of your code, you can end up with incorrect values!
Here's a sample epoch shift method (renamed from castAsUtc for clarity). First get the timezone offset from the object, then subtract it and create a new date with the new value. If you combine this with toISOString you'll get a date formatted as you wanted.
function epochShiftToUtc(date) {
var timezoneOffsetMinutes = date.getTimezoneOffset();
var timezoneOffsetMill = timezoneOffsetMinutes * 1000 * 60;
var buffer = new Date(date.getTime() - timezoneOffsetMill);
return buffer;
}
epochShiftToUtc(date).toUTCString();
I have the following data structure. The first column is intervals. The first row of the interval datum is a unix time and the subsequent data are intervals (i.e. 300*1, 300*2, ect). The other column is the data values. Here is the head of the data:
a1521207300,555.45
1,554.53
2,554.07
3,553.9
4,552.67
And here I went about converting the unix time to a Date object. The a here is ornamental, so I slice() at 1 like so:
var rawTime = data[0].interval;
var timeValue = Math.round(rawTime.slice(1));
console.log(timeValue)
console.log(new Date(timeValue))
I also tried using parseInt() instead of round(). The console shows that this unix time is equivalent to: Jan 18 1970 which I had quite the guffaw at. Then I got to thinking, maybe I did something wrong. It's supposed to be a very recent date -- March 16th 2018. This is strange because my understanding is that javascript can be passed a unix date directly as per this answer.
I also checked the unix time at a conversion site: www.onlineconversion.com/unix_time.htm
Which confirmed that it's indeed a March 16th 2018 timestamp.
Question: Why is this unix date for my March 2018 data being treated like a 1970's date? Maybe the a is actually doing something after all... Anyway, what is the correct way to handle this time stamp? It's only 10 numerical digits, it does not seem to be a precision problem. Date can handle unix times up to 13 digits I believe.
As per the documentation, when you invoke new Date(value) with an integer value, it is used as the number of milliseconds since January 1, 1970. To get the date you want, the value 1521207300 appears to be number of seconds instead of milliseconds. That is, you missed a factor of 1000. new Date(1521207300000) gives Fri Mar 16 2018.
When I take away new from new Date it seems to be ok. Not sure why though.
The documentation mentions the different behavior:
Note: JavaScript Date objects can only be instantiated by calling JavaScript Date as a constructor: calling it as a regular function (i.e. without the new operator) will return a string rather than a Date object; unlike other JavaScript object types, JavaScript Date objects have no literal syntax.
It seems when called as a function Date(value), it treats the value as the number of seconds, instead of milliseconds. I didn't dig deep enough to confirm this, because it doesn't matter: the documentation says to not use it this way (and since it gives a string instead of a date object, it's not very useful anyway).
Im using moment.js to convert a long/epoch time in to a humane readable format:
function convertValue(x) {
var mytime = x; // x = 1460554200000000
mytime = moment.utc(mytime).utcOffset(moment().format('ZZ'));
mytime = mytime.format('DD-MM-YY HH:mm:ss.SSS');
mytime = mytime + ' (' + moment().format('[UTC]ZZ') + ')';
return myTime;
}
Which myTime would return something like: 14-05-16 15:55:05.000 (UTC+100)
How can i do the opposite, so, if i was to receive something like: 29-01-16 14:35:05.000 (UTC+100) and convert back to an epoch time?
For a given moment object, if you want the result as a string:
Use .format('x') for the timestamp in milliseconds
Use .format('X') for the timestamp in seconds
However, if you want the result as a number:
Use .valueOf() for the timestamp in milliseconds
Use .unix() for the timestamp in seconds
However, with regards to the code you provided:
The offset UTC+100 is nonstandard and somewhat ambiguous. It could be UTC+10, UTC+10:00, UTC+0100, or UTC+01:00.
DD-MM-YY may be confusing to users, as it using two digit years, and is in reverse order of what is usually expected. Use YYYY-MM-DD if you're intending it to be used by a large number of people, or if you're going for something locale specific then make sure you're using separators that are common in the locale. Usually / or .
You're pairing the timestamp given with the current offset, rather than the offset in effect at the given time. That's going to fail in many locations where the time zone offset changes for daylight saving time and other time zone changes.
Your code should just be:
var mytime = moment(x).format('YYYY-MM-DD HH:mm:ss.SSS [UTC]ZZ');
To create a moment object from a string in a particular format, simply provide that format when parsing. So, the reverse function would be:
var x = moment(mytime, 'YYYY-MM-DD HH:mm:ss.SSS [UTC]ZZ').valueOf();
As long as you can coerce it back in to a moment object, you should be able to use moment().format('x') to get back to a Unix timestamp.
If you're talking about parsing a non standard date string in to a moment object, that's a lot more difficult. Since you know the format it was output as you should be able to use moment(dateString, formatString) to create a moment out of it.
I want to get the time difference between saved time and current time in javascript or jquery. My saved time looks like Sun Oct 24 15:55:56 GMT+05:30 2010.
The date format code in java looks like
String newDate = "2010/10/24 15:55:56";
DateFormat format = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
Date date = format.parse(newDate);
How to compare it with the current time and get the difference?
Is there any inbuilt function in jquery or javascript??
Any suggestions or links would be appreciative!!!
Thanks in Advance!
Update
Date is stored as varchar in the DB. I am retriving it to a String variable and then change it to java.util.Date object. The java code looks like
String newDate = "2010/10/24 15:55:56";
DateFormat format = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
Date date = format.parse(newDate);
This date object was sent to client. There i want to compare the saved date with current date and want to show the time difference like 2 secs ago, 2 hours ago, 2 days ago etc... like exactly in facebook. I have gone through some date to timestamp conversion tutorial in java script and now i can get the difference in timestamp. Now, i want to know how i shall change it to some format like "2 secs or 2 days or 24 hours"??. Or, how i shall change it back to date format???
Convert them into timestamps which are actually integers and can get subtracted from each other. The you just have to convert back the resulting timestamp to a javascript date object.
var diff = new Date();
diff.setTime( time2.getTime()-time1.getTime() );
You dont need to explicit convert, just do this:
var timediff = new Date() - savedTime;
This will return the difference in milliseconds.
jQuery doesn't add anything for working with dates. I'd recommend using Datejs in the event that the standard JavaScript Date API isn't sufficient.
Perhaps you could clarify exactly what input and output you're aiming for. What do you mean by "the difference?" There is more than one way to express the difference between to instants in time (primarily units and output string formatting).
Edit: since you said you're working with jQuery, how about using CuteTime? (Demo page)