Sorting UTC dates in javascript - javascript

EDIT 4/16/2012: I solved the issue of getting the timezone abbreviated into a letter format, had to download a third party sorting method and add a few things to get the desired results. The only problem now is Daylight Savings Time handlers, but there are a bunch of subjects on that. However if anyone knows how to handle UTC Daylight Savings hanlers, please feel free to help.
Thank you everyone.
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
I've made an html table that I've binded with a javscript viewmodel using knockoutjs that pulls the info from a private server usin JSON function. I'm trying to make each column sortable (click on the column header once to get everything in descending order according to that column's info; click header again to get everything in ascending, and a third time to get everything in it's original order).
PLEASE NOTE: I have searched for my problem and have seen other solutions, but nothing so far has worked for me. I'm hoping to find a solution specific towards my code.
The Javascript ViewModel.js file is basically like this:
Event(column1, column2, ...., columnN){
var self = this;
self.column1 = column1;
self.column2 = column2;
.
.
}
//Sort column2 that has the Dates (dd (day) HHMM (hours/minutes) mmm (month) yy (year) format)
self.sortColumn = "Column2"
self.sortAscending = true;
self.SortByDates = function(){
if(self.sortColumn == "Column2")
self.sortAscending = !self.sortAscending;
else{
self.sortColumn = "Column2"
self.sortAscending = true;
}
self.rows.sort(function(a,b){
if(self.sortAscending == true)
for(self.Column2 in self.rows)
return a.Column2 > b.Column2 ? 1 : a.Column2 < b.Column2 ? -1 : 0;
else
return a.Column2 < b.Column2 ? 1 : a.Column2 > b.Column2 ? -1 : 0;
});
}
//specify location of server and info and get them
function getEvents(){
$.getJSON("http://.........",
function (data){
$.each(data.d, function(i, item){
handleEvent(item)
})
}
);
}
//pushes (AKA populates) info from server into the table
function handleEvent(item){
var newEvent = new Event(item.Column1InfoFromServer,
formatJSONDate(item.Column2DateInfoFromServer), .....)
this.Model.rows.push(newEvent);
}
//Formats the date info from server into dd (day) HHMM (hours/minutes) mmm (month) yy (year)
formatJSONDate(jsonDate){
var date = new Date(parseInt(jsonDate.substr(6)));
return date.format("dd HHMM mmm yy");
}
this.Model = new ViewModel();
this.getEvents();
ko.applyBindings(this.Model);
I'm having one hell of a hard time getting the Date in its converted form (yes it HAS to be in that form --> actually, I still need to figure out how to include the time-zone abbreviation right after the 'HHMM' part based off of UTC). So lets say I have "11 1136 Apr 12" and "22 1624 Jan 12" among other dates in the table. Right now when I try sorting the table according to the dates, they don't sort appropriately. Any help is appreciated, thank you.
EDIT: To be clear, I'm trying to display the timezones in military timezone codes (timezones 'A'-'Z'). Also, the dates being taken from the server are already in UTC.

UPDATE:
I was looking at another question, and someone created a knockout grid addon:
https://github.com/ericmbarnard/KoGrid
I bet this might help you out :-)
---OLD ANSWER for nostalgia----
There are some great helper functions in the Underscore library, one of them being sort:
http://documentcloud.github.com/underscore/#sortBy
sortBy_.sortBy(list, iterator, [context]) Returns a sorted copy of
list, ranked in ascending order by the results of running each value
through iterator. Iterator may also be the string name of the property
to sort by (eg. length).
_.sortBy([1, 2, 3, 4, 5, 6], function(num){ return Math.sin(num); });
=> [5, 4, 6, 3, 1, 2]
I'd give this a shot, along with creating a better model for your dates. It sounds like you need to store a property which is a unique point in time, along with a text value for the user.

Well, to get numeric values for your date objects, sort by pDate.valueOf(). This will give you the # of millisecond since epoch.
However, there is an issue inside of your sort function, but I'm not sure what it is supposed to do. You can't walk an object inside of a sort function and return values like that.

Related

Using moments js to create a date array

Does anyone know how i can use moment js , to create a dynamic dates array , that contains todays date and dates of next 9 days.
so im creating a scheduler that will run on some days(not yet specified) when it runs its supposed to prepare some reports on todays date and next 9 days, my idea is to create an array of dates and map through them but i cant figure out how to create such an array using moment js , any ideas ?
i checked some legacy code and they are using the following to get present date
const now = moment().add(-moment().utcOffset(), 'minutes').toDate()
I think this is a good candidate for a traditional for loop solution, using an offset and the moment .add method to build an array adding the offset as you go, ending up with a ten-day array where the first element at index 0 holds the value of your now variable.
const moment = require('moment')
const date = moment().add(-moment().utcOffset(), 'minutes').toDate()
const reportDates = [];
for (let dayOffset = 0; dayOffset < 10; dayOffset++) {
const nextDate = moment(date).add(dayOffset, 'days').toDate();
reportDates.push(nextDate)
}
console.log(reportDates)
Output when I ran this snippet on my machine (# ~10:22 Central US time):
[
2022-11-29T22:22:51.788Z,
2022-11-30T22:22:51.788Z,
2022-12-01T22:22:51.788Z,
2022-12-02T22:22:51.788Z,
2022-12-03T22:22:51.788Z,
2022-12-04T22:22:51.788Z,
2022-12-05T22:22:51.788Z,
2022-12-06T22:22:51.788Z,
2022-12-07T22:22:51.788Z,
2022-12-08T22:22:51.788Z
]
The moment.js vs other libraries is another discussion, and if at all possible to use a different library I would recommend date-fns to avoid any confusion in the future from the mutability built into moment objects.
Good luck!

how to send datetime dataframe to django template and plot it in js using plotly

I have a data-frame and I want to send it in my Django template.
dummy code in views.py:
def graphs(request):
df_new = pd.read_excel("/home/cms/cms/static/Sensorik.xlsx")
times = df_new.loc[:, df_new.columns[0]].to_json(orient='records')
# columns[0] contains datetime values
data_color = df_georgian.loc[:, df_georgian.columns[2]]
color = data_color.to_json(orient='records')
context = {
'times': times,
'data_color': color,
...
}
return render(request, 'graphs/graphs.html', context)
In my template, I get these data like the following:
<script>
var times = {{ times|safe }};
console.log('index: ', typeof(index));
var color = {{ data_color|safe }};
</script>
the color variable is totally ok but the times variable when get to JSON format turns from 2018-05-29 08:09:00 format to something like it:
element: 1528108200000
I want to be able to plot the color based on times to get a line graph with plotly. i.e. I want to show times as x-ticks of my plot.
any suggeston on
1- how to send datetime dataframe to django template?
or
2- how to convert element: 1528108200000 into a datetime in js to plot it as x-ticks?
Whenever you see something that should be a date or time expressed in a large number like the 1528108200000 format, that means it is or is similar to a UNIX timestamp—the number of seconds past January 1, 1970. In this case, the length of the timestamp indicates that it's milliseconds, not seconds, so it's not exactly a UNIX timestamp but is very close.
Milliseconds since January 1, 1970 is the way that JS internally stores Date objects, which is interesting because it means some sort of conversion is probably happening on the JS side, not the python side (where you'd usually get ISO format or UNIX Timestamps).
In any case, it's pretty easy to solve on the JS side because you can simply parse the number:
dateObject = new Date(1528108200000);
If you do that parsing and pass the data to Plotly as Date objects, Plotly should be able to recognize your dates.
A simple way to do that would be:
const times = [1528108200000, 1528108200000, 1528108200000]
const parsed = times.map(time => new Date(time))
assuming your times variable is just an array of these integers.

barChart plot with time dimension

I would like to make a bar chart where x-axis is date e.g. 2017-08-12, and the y value is the number of data rows (i.e. records count) on the same date.
// get data into right format
var dateFormat = d3.time.format("%Y-%m-%d");
pageViews.forEach(function(d) {
d['timestamp'] = dateFormat.parse(d['timestamp'].slice(0,10));
d['timestamp'].setDate(1);
});
// Create Crossfilter instance
var cf = crossfilter(data);
var dateDim = cf.dimension(function(d) {return d['timestamp'];});
var numByDate = dateDim.group();
but if I do
console.log(numByDate.top(Infinity));
this returns 5 elements that are the first day of each month, so the group I have is in terms of Year-Month instead of Year-Month-Day, how can I resolve this?
I looked into this crossfilter.js: group data by month, but it did not work, after using .all() I still get the same thing back.
And I tried this:
var numByDate = dateDim.group(function(d) {return d['timestamp'];});
it just returns me an empty object.
So this is a result of my unfamiliarity with js and copy paste example code ...
The issue comes from misuse of the setDate method,
setDate(1)
would just set the day of the month in the data to the first day, so the group method would only have several unique dates to work with.

Full Calendar get cell attributes by date range

So I'm using Full Calendar JavaScript in my project. I set an attribute to each day cell inside day render function. Question: Can I get those attributes using date range? Is that doable? Any suggestions are much appreciated thanks.
Each of the day cells has the class fc-day, and each of them has a property data-date showing the date it represents (e.g. 2017-09-19).
So for example, let's say you are in a month view showing September 2017, and a custom attribute called "MyCustomAttr" (showing what day of the whole year that day is) has been added to those date cells via dayRender, like this:
dayRender: function(date, cell) {
cell.attr("MyCustomAttr", "Day Of Year: " + date.format("DDD"));
},
Then, you want to get the custom attribute values of all the cells in the range 10th-15th September (exclusive), you can run this code (as long as it runs at some time after the dayRender callback was executed):
var days = $(".fc-day");
var attributes = [];
var rangeStart = moment("2017-09-10");
var rangeEnd = moment("2017-09-15");
days.each(function(index, element) {
var day = moment($(this).data("date"));
if (day.isBetween(rangeStart, rangeEnd))
{
attributes.push($(this).attr("MyCustomAttr"));
}
});
console.log(JSON.stringify(attributes));
You can see a working example here: http://jsfiddle.net/sbxpv25p/20/
N.B. I have just put the attribute values into an array as an example, which isn't very useful in itself, since they aren't associated with the days anymore. You didn't say what you wanted to do with the attributes once you've got them, so I'll leave it to you to modify the example to suit your needs.

Laravel get all data from database and put it into a chart

I'm working with Laravel 4 to build an applicaton.
Now, I do count all my visitors in a 'unique' way. So the system does chack if there was already a visit this day and if so, it just counts a click in the database.
What my database structure look like:
I want the system to count the visitors (so the IP adressess) of day X in month X. Like the visitors of 30/04/2015 wich is in my table 2015-04-30. I want to count all the IP adressess of that day and the other days of a month. But when the month is over, it needs to get the values of the next month, so I want the values of the current month.
The hits are just to count the 'clicks' on my site, so don't need to mention that.
The date and visit_date give me the current date of visiting and visit_time gives me the time of the visit.
My current code looks like this to display the values:
public function index()
{
$select_stats = DB::table('visitor')->whereBetween('visit_date', array(date('Y-m-01'), date('Y-m-t')))->get();
$month = date('m');
$get_count = DB::select(DB::raw("SELECT count(*) FROM visitor WHERE MONTH(date) = $month GROUP BY DAY(date)"));
foreach($select_stats as $statics) {
//change our object to an array
$statics = array();
}
return View::make('admin.home.index')->with('stats', $select_stats)/*->with('count', $get_count)*/;
}
But When I try to display this code, with the counted numbers, it doesn't work anymore. My view looks like this:
<script type="text/javascript">
var visitors = [
#foreach($stats as $stat)
['{{ date("d/m/Y", strtotime($stat->date)) }}', 55],
#endforeach
];
</script>
So the 55 inside of my view are the counted visitors as output.
Could someone help me as soon as possible please?
Kindest regards,
Robin
I'm not really understanding all that well, but a few things that could help... 1. I'd really suggest looking into using model classes in stead of using DB raw queries. Thats where Laravel is really great. For example it would be:
$select_stats= Visitor::where('visit_date', '>=', Carbon::now()->startOfMonth())->get();
$get_count = $select_stats->count();
In stead of doing a foreach in the script, I'd return a json array. So you could send the 'stats' variable to your view instead as:
with('stats', $select_stats->lists('visit_date'))
and then in the script you'd just have to use:
{{ json_encode($stats) }}

Categories