Converting a string into a date - javascript

I have the following script which joins 2 feeds and displays them on the screen
$.when( //get feed 1, //get feed 2 ).done(function(a1, a2){
var data = a1[0]response.Data.feed.entries.concat(a2[0].responseData.feed.entries);
var sorted = data.sort(function(a, b) {
if(a.publishedDate > b.publishedDate) {
return 1
}
if(a.publishedDate < b.publishedDate) {
return -1
}
return 0
});
for( i = o; i <= sorted.length - 1; i++ ) {
document.write(sorted[i].title);
document.write(sorted[i].publishedDate);
}
});
This returns all the rows, but it doesn't sort the rows. The sorting seems completely random. I'm assuming it's because the dates are formatted as follows in the JSON data:
Mon, 23 Sep 2013 04:37:45 -0700
What does that -0700 mean
How do I convert that date string into a proper date object so I can sort the results correctly?

-0700 means the UTC offset UTC-07:00.
I'm strongly recommend you to use Moment.js library to deal with date and time, formatting and conversions to make your "Date & Time JavaScript Life" easy and funny.
As Alnitak said this particular format is accepted by Date.parse therefore if you use one of accepted formats you can just use native JavaScript for sorting.
var dateStrings,
sortDates;
dateStrings = [
'Mon, 23 Sep 2013 04:37:45 -0700',
'Sun, 22 Sep 2013 05:27:32 +0300',
'Mon, 23 Sep 2013 03:14:17 -0700'
];
sortDates = function(dateStrings) {
return dateStrings.sort(function(a, b) {
return new Date(a) - new Date(b);
});
};
console.log(sortDates(dateStrings));
Fiddle
The variable sorted in your code snippet could be properly retrieved in this way:
var sorted = data.sort(function(a, b) {
return new Date(a.publishedDate) - new Date(b.publishedDate);
});

Well, -0700 means.. is 7 hours earlier than Greenwich Mean ...yor can check more in wikipedia
And if you want to convert any date properly, i strongly recommend you to use the library DateJS (http://www.datejs.com/)
You can use syntatic sugarr..!! to create your object...
Date.parse('Thu, 1 July 2013 20:20:20');
voila.. its very easy...

You can pass the string to new Date(...) to convert to a real Date object.
To sort however you also need to pass a specific sort function because default Javascript sort on arrays just converts elements to string and compares the result of conversion (thus any "Mon"day will happen to be placed before any "Sun"day).
Something that should work is
dates.sort(function(a, b){ return a - b; });

Related

Date String sorting in trNgGrid

My column contains a list of dates in string format. Eg.: "Aug 2013", "Sep 2012" etc
But when I try to sort, it sorts alphabetically. One approach I thought of was to convert it to epoch format by using javascript.
new Date("Aug 2013").getTime()
This returns a long value in epoch format 1375295400000 and I believe I can sort it then.
I have trouble integrating it in the frontend code. Is there any way I can achieve this?
To sort your list of dates (in string format), you can use the sort function with a custom comparison function. This comparison function converts the two strings to date objects then to millisecond and returns the difference.
var list = ["Aug 2013", "Sep 2012", "Sep 2010"];
var sli = list.sort(function (a, b) {
var d1 = new Date(a).getTime();
var d2 = new Date(b).getTime();
return d1 - d2;
});
res.end('sli='+sli);
Output:
sli=Sep 2010,Sep 2012,Aug 2013
Alright the fix was pretty simple. I passed the UTC time format in JSON data as utcTime. Hence in the TrNgGrid column declaration
field-name="utcTime" display-format="displayTimePeriod:gridItem"
And in the angular module define displayTimePeriod filter as
.filter("displayTimePeriod", function() {
return function(fieldValueUnused, item) {
return item.timePeriod;
}
})
So sorting happens based on utcTime variable but in the view I have timePeriod displayed.

Javascript sorting dates in the wrong order

I can't figure out why Javascript (running in Chrome, Safari, or NodeJS) seemingly sorts these dates incorrectly:
> [
"2014-05-01T08:06:00.000Z",
"2014-05-01T06:26:00.000Z",
"2014-05-01T06:27:00.000Z"
].map(function(x) {return new Date(x)}).sort()
produces
[ Thu May 01 2014 01:06:00 GMT-0700 (PDT),
Wed Apr 30 2014 23:26:00 GMT-0700 (PDT),
Wed Apr 30 2014 23:27:00 GMT-0700 (PDT) ]
I have looked for odd time changes around that date but can't find any.
Simply calling sort method will basically sorting based on string comparison. So for sorting based on date object use custom sort function.
console.log(
[
"2014-05-01T08:06:00.000Z",
"2014-05-01T06:26:00.000Z",
"2014-05-01T06:27:00.000Z"
].map(function(x) {
return new Date(x)
}).sort(function(a, b) {
return a - b;
})
)
If you want to sort the original array then avoid map method and inside the compare function parse the date string before taking difference.
console.log(
[
"2014-05-01T08:06:00.000Z",
"2014-05-01T06:26:00.000Z",
"2014-05-01T06:27:00.000Z"
].sort(function(a, b) {
return new Date(a) - new Date(b);
})
)
Array.prototype.sort takes a callback which can return negative, positive or zero value to sort the target array.
[
"2014-05-01T08:06:00.000Z",
"2014-05-01T06:26:00.000Z",
"2014-05-01T06:27:00.000Z"
].sort(function(a, b){
return (new Date(b) - new Date(a));
})

How to JSON stringify a javascript Date and preserve timezone

I have a date object that's created by the user, with the timezone filled in by the browser, like so:
var date = new Date(2011, 05, 07, 04, 0, 0);
> Tue Jun 07 2011 04:00:00 GMT+1000 (E. Australia Standard Time)
When I stringify it, though, the timezone goes bye-bye
JSON.stringify(date);
> "2011-06-06T18:00:00.000Z"
The best way I can get a ISO8601 string while preserving the browser's timezone is by using moment.js and using moment.format(), but of course that won't work if I'm serializing a whole command via something that uses JSON.stringify internally (in this case, AngularJS)
var command = { time: date, contents: 'foo' };
$http.post('/Notes/Add', command);
For completeness, my domain does need both the local time and the offset.
Assuming you have some kind of object that contains a Date:
var o = { d : new Date() };
You can override the toJSON function of the Date prototype. Here I use moment.js to create a moment object from the date, then use moment's format function without parameters, which emits the ISO8601 extended format including the offset.
Date.prototype.toJSON = function(){ return moment(this).format(); }
Now when you serialize the object, it will use the date format you asked for:
var json = JSON.stringify(o); // '{"d":"2015-06-28T13:51:13-07:00"}'
Of course, that will affect all Date objects. If you want to change the behavior of only the specific date object, you can override just that particular object's toJSON function, like this:
o.d.toJSON = function(){ return moment(this).format(); }
I'd always be inclined to not mess with functions in the prototype of system objects like the date, you never know when that's going to bite you in some unexpected way later on in your code.
Instead, the JSON.stringify method accepts a "replacer" function (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#The_replacer_parameter) which you can supply, allowing you to override the innards of how JSON.stringify performs its "stringification"; so you could do something like this;
var replacer = function(key, value) {
if (this[key] instanceof Date) {
return this[key].toUTCString();
}
return value;
}
console.log(JSON.stringify(new Date(), replacer));
console.log(JSON.stringify({ myProperty: new Date()}, replacer));
console.log(JSON.stringify({ myProperty: new Date(), notADate: "I'm really not", trueOrFalse: true}, replacer));
Based on Matt Johnsons 's answer, I re-implemented toJSON without having to depend on moment (which I think is a splendid library, but a dependency in such a low level method like toJSON bothers me).
Date.prototype.toJSON = function () {
var timezoneOffsetInHours = -(this.getTimezoneOffset() / 60); //UTC minus local time
var sign = timezoneOffsetInHours >= 0 ? '+' : '-';
var leadingZero = (Math.abs(timezoneOffsetInHours) < 10) ? '0' : '';
//It's a bit unfortunate that we need to construct a new Date instance
//(we don't want _this_ Date instance to be modified)
var correctedDate = new Date(this.getFullYear(), this.getMonth(),
this.getDate(), this.getHours(), this.getMinutes(), this.getSeconds(),
this.getMilliseconds());
correctedDate.setHours(this.getHours() + timezoneOffsetInHours);
var iso = correctedDate.toISOString().replace('Z', '');
return iso + sign + leadingZero + Math.abs(timezoneOffsetInHours).toString() + ':00';
}
The setHours method will adjust other parts of the date object when the provided value would "overflow". From MDN:
If a parameter you specify is outside of the expected range, setHours() attempts to update the date information in the Date object accordingly. For example, if you use 100 for secondsValue, the minutes will be incremented by 1 (minutesValue + 1), and 40 will be used for seconds.
When I stringify it, though, the timezone goes bye-bye
That’s because Tue Jun 07 2011 04:00:00 GMT+1000 (E. Australia Standard Time) is actually the result of the toString method of the Date object, whereas stringify seems to call the toISOString method instead.
So if the toString format is what you want, then simply stringify that:
JSON.stringify(date.toString());
Or, since you want to stringify your “command” later on, put that value in there in the first place:
var command = { time: date.toString(), contents: 'foo' };
If you have a JS Date Object and want to stringify it to preserve the timezone, then you should definitely use toLocaleDateString().
It is a very powerful helper function that can help you format your Date object in every way possible.
For example, if you want to print "Friday, February 1, 2019, Pacific Standard Time",
const formatDate = (dateObject : Date) => {
const options: any = {
weekday: 'long',
year: 'numeric',
month: 'long',
day: 'numeric',
timeZoneName: 'long'
};
return dateObject.toLocaleDateString('en-CA', options);
};
Thus, by modifying the options object, you can achieve different styles of formatting for your Date Object.
For more information regarding the ways of formatting, refer to this Medium article: https://medium.com/swlh/use-tolocaledatestring-to-format-javascript-dates-2959108ea020
let date = new Date(JSON.parse(JSON.stringify(new Date(2011, 05, 07, 04, 0, 0))));
I've created a small library that preserves the timezone with ISO8601 string after JSON.stringify. The library lets you easily alter the behavior of the native Date.prototype.toJSON method.
npm: https://www.npmjs.com/package/lbdate
Example:
lbDate().init();
const myObj = {
date: new Date(),
};
const myStringObj = JSON.stringify(myObj);
console.log(myStringObj);
// {"date":"2020-04-01T03:00:00.000+03:00"}
The library also gives you options to customize the serialization result if necessary.

Javascript date less than or equal to returning only less than

I have a jQuery datepicker tool returning back a maximum and a minimum date.
The dates are to filter out results from an array. I use jQuery.grep to filter based on the date. For some reason, while >= will work, <= only returns less than.
// Function to filter based on date minimum
function filterListGreaterThan(filter, list, min){
var result = jQuery.grep(list, function (obj){
return new Date(obj[filter]) >= min;
});
return result;
};
function filterListLessThan(filter, list, max){
var result = jQuery.grep(list, function (obj){
return new Date(obj[filter]) <= max;
});
return result;
};
So if i put in Nov 1, 2013 - Nov 5, 2013 it will only return Nov 1 - Nov 4... and I have no idea why.
Edit: Mac gave me the correct answer. When comparing the dates jQuery Sets the time to midnight. So even though I had it searching on the correct day it was not looking past midnight. This is the Corrected function:
// Function to filter based on date maximum
function filterListLessThan(filter, list, max){
var result = jQuery.grep(list, function (obj){
//add time to date because jQuery sets the time at 00:00:00
max.setHours(23,59,59);
return new Date(obj[filter]) <= max;
})
return result;
};
It seems the problem is likely due to the max date having a time component set to 00:00 AM - all items in the array occurring on the max date are probably being filtered out because they occur some time after 00:00 AM.
To fix this, the best approach is either to change the max date to have a time component of 11:59:59 PM, or to set the max date to 00:00 AM the following day and use a less-than (rather than a less-than-or-equal).
Not entirely sure I understand what you are trying to do, so apologies if this is not what you need but if you just want to filter an array of dates I'd try something like below.
You need to make sure you are comparing a Date object with another Date object and that the values in your array are formatted so as to make a valid Date object.
I'm not sure how that jQuery function works but using vanilla javascript I would do something like this to filter dates:
var list = ['2013,10,01','2013,10,02','2013,10,03','2013,10,04','2013,10,05',
'2013,10,06'];
function filterListGreaterThan(list, min_date){
var filtered_dates = [];
for(var i=0; i < list.length; i++){
var parts = list[i].split(','),
test_date = new Date(parts[0],parts[1],parts[2]);
if(test_date >= min_date){
filtered_dates.push(test_date);
}
}
return filtered_dates;
}
var min_date = new Date('2013','10','04'),
dates = filterListGreaterThan2(list, min_date);
console.log(dates);
//RETURNS:
//Mon Nov 04 2013 00:00:00 GMT+0000 (GMT Standard Time)
//Tue Nov 05 2013 00:00:00 GMT+0000 (GMT Standard Time)
//Wed Nov 06 2013 00:00:00 GMT+0000 (GMT Standard Time)
//

Simple Javascript date conversion

I have this - Tue, 03 Apr 2012 05:00:33 GMT
Need this - 20120323111106
Google has failed me, I think I just don't know exactly what im searching for so I kept it simple here with the question.
EDIT: The dates do not match obviously, just looking to get it in that format.
Good answer (later edited):
I think this is what you are looking for :
function addZero(val){
if (parseInt(val) < 10) return "0" + val;
return val;
}
var dt = new Date("Tue, 03 Apr 2012 05:00:33 GMT");
console.log(dt.getFullYear() + addZero(dt.getMonth()) + addZero(dt.getDay()) + addZero(dt.getHours()) + addZero(dt.getMinutes()) + addZero(dt.getSeconds()))
Initial wrong answer :
var dt = new Date("Tue, 03 Apr 2012 05:00:33 GMT")
var miliseconds = dt.getTime();
I've tested it and my computer converted it automatically to GMT +3 (my timezone), you can play with that according to your timezone.
Writing a function to parse a string should work for you. By the looks of it, any date string that you currently have will be the same length. If this is the case this should be relatively easy. Just make sure your strings are in this format before you pass them in as arguments.
function parse(string) {
var out = "yyyymmddhhmmss"
out.charAt(0) = string.charAt(13);
out.charAt(1) = string.charAt(14);
out.charAt(2) = string.charAt(15);
out.charAt(3) = string.charAt(16);
//if else statements for each month converting to numbers
if (string.substring(9,12).equals("Apr")) {
out.charAt(4) = '0';
out.charAt(5) = '4';
}
out.charAt(6) = string.charAt(18);
out.charAt(7) = string.charAt(19);
...etc for the remaining values
return out
}
My numbers for character indices may be off, but if you use this idea, it should set you straight. Define a function and pass in the dates in the format you have, and out will come the dates in the format you want.

Categories

Resources