Is there a natural language parser for date/times in javascript?
I made Chrono a small library for parsing dates in JavaScript. I added a date range parsing feature (such as '12 Nov - 13 Dec 2012') .
SugarJS supports some natural language parsing of dates and times.
You can jump to the live example here: http://sugarjs.com/dates
For example, it supports the following inputs:
the day after tomorrow
2 weeks from monday
May 25th of next year
You can then covert the result into different date formats or use the API to further manipulate the date.
Does Date.js satisfy your needs? Or are you looking for something else?
Chrono v2 is the only library I've found that also parses timezones.
Unfortunately, the only documented way of using it is via NPM (npm i chrono-node) or as ES6 Module (import * as chrono from 'chrono-node'), but I found a way to use the library with the traditional script tag approach for those interested.
Non-NPM / non-module usage:
Include this script: https://www.unpkg.com/chrono-node/dist/bundle.js
Use the global variable chrono in your script (available methods here)
E.g. chrono.parseDate('Tomorrow at 4 PM PST')
⚠ Note: I have not tested this extensively, so don't expect it to work flawlessly
For node, I've found chrono to work well
Chrono supports most date and time formats, such as :
Today, Tomorrow, Yesterday, Last Friday, etc
17 August 2013 - 19 August 2013
This Friday from 13:00 - 16.00
5 days ago
2 weeks from now
Sat Aug 17 2013 18:40:39 GMT+0900 (JST)
2014-11-30T08:15:30-05:30
Sherlock is a great one.
var Sherlock = require('sherlockjs');
var sherlocked = Sherlock.parse('Homework 5 due next monday at 3pm');
// Basic properties
var title = sherlocked.eventTitle; // 'Homework 5 due'
var startDate = sherlocked.startDate; // Date object pointing to next monday at 3pm
var endDate = sherlocked.endDate; // null in this case, since no duration was given
var isAllDay = sherlocked.isAllDay; // false, since a time is included with the event
// Example of an additional custom property added by Watson
var validated = sherlocked.validated; // true
You can use the jQuery datepicker translation, get the day and month number and select the day from datepicker days.
You can add values to this object, and you can download up to 60 languages I think. (The object below is not complete, I removed some code to simplify it).
$.datepicker.regional['sv'] = {
monthNames:['Januari','Februari','Mars','April','Maj','Juni','Juli','Augusti','September','Oktober','November','December'],
monthNamesShort: ['Jan','Feb','Mar','Apr','Maj','Jun','Jul','Aug','Sep','Okt','Nov','Dec'],
dayNamesShort: ['Sön','Mån','Tis','Ons','Tor','Fre','Lör'],
dayNames: ['Söndag','Måndag','Tisdag','Onsdag','Torsdag','Fredag','Lördag'],
dayNamesMin: ['Sö','Må','Ti','On','To','Fr','Lö']
};
Now get the day and month number
var dateObject = new Date();
var day = dateObject.getDay();
var month = dateObject.getMonth();
var monthText = $.datepicker.regional['sv']['monthNames'][month];
var dayText = $.datepicker.regional['sv']['dayNames'][day];
Related
Moment.js is a very usefull JavaScript library which provides many functions to manipulate date formatting.
In order to create a Moment object, it is possible to parse a string simply moment("1995-12-25"); or by providing format moment("12-25-1995", "MM-DD-YYYY");.
Another feature allows us to use relative dates : moment("1995-12-25").fromNow() // 19 years ago.
However, I can not find a way to parse such a relative date. When I try moment("19 years ago") it just returns Invalid date, and it does not exist any token to properly format the date.
Is there an easy way to do this? Or is it a missing feature that should be suggested on Github?
Just found chrono wile looking to see if NLP had already been implemented in momentjs. It looks like it handles parsing NLP to a date, which can be used to create a momentjs date.
Simply pass a string to function chrono.parseDate or chrono.parse.
> var chrono = require('chrono-node')
> chrono.parseDate('An appointment on Sep 12-13')
Fri Sep 12 2014 12:00:00 GMT-0500 (CDT)
And a quick example showing how that would work
Code
const moment = require('moment')
const chrono = require('chrono-node')
let now = moment()
console.log(now)
let yrsAgo = chrono.parseDate("19 years ago")
console.log(yrsAgo)
let yrsAgoMoment = moment(yrsAgo)
console.log(yrsAgoMoment)
Output
$node test.js
moment("2017-06-30T08:29:20.938")
1998-06-30T17:00:00.000Z
moment("1998-06-30T12:00:00.000")
The only way of doing this is moment().sub(19, 'years');
What you are asking imply a Natural language processing which is whole computer science field.
There is a plugin which very recently appeared on github, which is a plugin to moment to allow this sort of parsing: https://github.com/cmaurer/relative.time.parser
I have not personally tried it, but I will shortly (found both it and this question while searching for the same thing).
What about :
moment.fn.parse = function(_relative, _format){
var _modulo = moment.normalizeUnits(_format);
return this.add(_relative, _modulo);
}
moment("30/08/2015", "DD/MM/YYYY").parse(-20, "years").format('DD/MM/YYYY'); // 30/08/1995
moment("30/08/2015", "DD/MM/YYYY").parse(-2, "week").format('DD/MM/YYYY'); // 16/08/2015
moment("30/08/2015", "DD/MM/YYYY").parse(-2, "d").format('DD/MM/YYYY'); // 28/08/2015
I wrote the plugin relative.time.parser. The original intent was to parse relative time from graphite from/until, so I was only going for the 'reverse' in time.
I will take a look at adding the 'NLP' use cases as well.
Thanks,
Chris
You can do it easily using moment plus little logic. Here it is working perfectly
function parseSincUntilDate(dateStr, now = new Date()) {
// inputs: 20 minutes ago, 7 hours from now, now, '', or UTC string
if (moment(dateStr).isValid()) return moment(dateStr).toDate();
const tokens = dateStr.split(' ');
if (dateStr.includes('ago')) {
return moment(now).subtract(tokens[0], tokens[1]).toDate();
} else if (dateStr.includes('from now')) {
return moment(now).add(tokens[0], tokens[1]).toDate();
} else if (dateStr === 'now' || dateStr === '') {
return new Date(now);
}
return moment(dateStr).toDate();
}
// to change relative date, pass it in second parameter
As of Moment.js 1.0.0 (October 2011) to current:
moment().add(7, 'days');
moment().subtract(1, 'seconds');
Works with years, quarters, months, weeks, days, hours, minutes, seconds, and milliseconds.
https://momentjs.com/docs/#/manipulating/add/
https://momentjs.com/docs/#/manipulating/subtract/
Having searched endlessly for an answer, nothing has so far worked - so here I am hoping someone can assist.
I have 2 fields:
Action_Date & Deadline
The user updates the Action_Date field with the date they worked on the item. I then need to auto-populate the Deadline field with Action_Date + 14 days.
I have tried this so far:
function testCalc() {
var actionDate = new Date(document.getElementById("Action_Date").value);
var sla = 14;
var deadline = actionDate + sla;
document.getElementById("Deadline").value = deadline;
}
Action_Date calls this function via onblur()
The Deadline field auto-populates with the same date as Action_Date, in full format (e.g. Thu Jan 01 2015 00:00:00 GMT+0000(GMT Standard Time)14
Clearly the 14 days are not adding. Additionally I need Deadline to show the result in dd/mm/yy.
Any ideas most welcome!
Javascript dates are in milliseconds by default. So adding "14" to it is simply adding 14 milliseconds not 14 days. You will need to investigate more about Javascript Dates() here:
http://www.w3schools.com/jsref/jsref_obj_date.asp
Or use a framework of some kind like moments.js which is one of the best date handling frameworks out there. Date manipulation is one of the more complex things we developers have to do on the web due to issues with their local time, server time, etc.
I need to parse and manipulate Times without Dates in my code. For example i might get the string "15:00" from a timepicker. I want to turn this into a Time object of some kind - I normally work in Python which has distinct Date, Time, and Datetime objects.
However all the solutions i've seen focus on using the Date object. This cannot parse a string like "15:00" since it requires day information. I don't want to add arbitrary Date information to Times - especially since Date appears to make assumptions about things like daylight saving depending on the day and the locale, and there appears to be a risk of it automatically attempting to translate the time into a given locale. Furthermore I want to be able to add times, e.g. "15:00 + 1 hour"
What is the recommended solution to parse and handle "raw" times not associated to dates?
Here's a moment.js solution for 12 or 24 hour times:
moment('7:00 am', ['h:m a', 'H:m']); // Wed Dec 30 2015 07:00:00 GMT-0600 (CST)
moment('17:00', ['h:m a', 'H:m']); // Wed Dec 30 2015 17:00:00 GMT-0600 (CST)
moment('17:00 am', ['h:m a', 'H:m']);// Wed Dec 30 2015 17:00:00 GMT-0600 (CST)
moment('17:00 pm', ['h:m a', 'H:m']);// Wed Dec 30 2015 17:00:00 GMT-0600 (CST)
http://momentjs.com/docs/#/parsing/string-formats/
Unfortunately, there's not a great solution. JavaScript only has a Date object, which is probably misnamed since it is really a date+time.
One thing you might want to think about deeper - you say you want to work with only time, but do you mean a time-of-day or do you mean a duration of time? These are two related, but slightly different concepts.
For example, you said you might want an operation like "15:00 + 1 hour". Well that would clearly be 16:00 either way. But what about "15:00 + 10 hours"? It would be 25:00 if you are talking about a duration, but it might be 01:00 if you are talking about time-of-day.
Actually, it might not be 01:00, since not all days have 24 hours in them. Some days have 23, 23.5, 24.5, or 25 hours, depending on what time zone and whether DST is starting or stopping on that day. So in the time-of-day context, you probably do want to include a particular date and zone in your calculation. Of course, if you are talking about straight 24-hours days, then this point is irrelevant.
If you are talking about durations - you might want to look again at moment.js, but not at the moment object. There is another object there, moment.duration. The reference is here.
And finally, you might want to consider just using plain javascript to parse out hours and minutes from the time string as numbers. Manipulate the numbers as necessary, and then output a string again. But your question seems like you're looking for something more managed.
I ended up using the following since I was already using moment in my app:
var str = '15:16:33';
var d = new moment(str, 'HH:mm:ss');
See Moment String+Format docs for other format strings you can use.
And I know I am over 8 years late to this party, but it is worth noting that moment.js is no longer being developed and is on a pacemaker for maintenance. They actually do NOT recommend using moment.js for new apps.
More details are found here: https://momentjs.com/docs/
I had to do this recently for a project but didnt really need to include moment.js, the method I used was to manually parse the time like this:
function parseTime(time) {
let timeInt = parseInt(time);
let minutes = time.substring(3,5);
// you could then add or subtract time here as needed
if(time > '12:00') {
return `${timeInt - 12}:${minutes} PM`;
} else {
return `${timeInt}:${minutes} AM`;
}
}
Use this as an alternative starter if you don't want to use moment. Note this example uses es6 syntax.
Okay, so I know I'm way late to the party. Like 6 years late but this was something I needed to figure out and have it formatted HH:mm:ss (24 hours).
moment().format(moment.HTML5_FMT.TIME_SECONDS); // 17:44:56
You can also pass in a parameter like, 2019-11-08T17:44:56.144.
moment('2019-11-08T17:44:56.144').format(moment.HTML5_FMT.TIME_SECONDS); // 17:44:56
https://momentjs.com/docs/#/parsing/special-formats/
I know I am writing this 8 years later but it's no longer advisable to use the moment.js library nowadays since it's no longer supported, luxo.js is the preferred(like the evolution of moments.js) one you can find more here: https://moment.github.io/luxon/api-docs/index.html
We know that the Date class in JavaScript must always contain a date, and entering time alone is not enough.
But when asked, I do not need to enter a date. This could mean:
You intend to compare two dates with each other.
The two dates are shared on the same day.
If so, then as a trick, you can add a specific date(any date) to your time as string. (E.g. 0000-01-01 )
For example, this code is incorrect:
var d1 = '00:53:57.123';
var d2 = '00:53:58.124';
console.log(new Date(d2).getTime() - new Date(d1).getTime());
//result: NaN
But this way you can get the right result:
var d1 = '00:53:57.123';
var d2 = '00:53:58.124';
d1 = '0000-01-01 ' + d1;
d2 = '0000-01-01 ' + d2;
console.log(new Date(d2).getTime() - new Date(d1).getTime());
//result: 1001
I am trying to get future and past dates programatically based on the current time. I am not sure if I am just dumb or I am truly doing something wrong. So I have 2 questions
Does Node.js or the V8 engine have getMinutes, getMonth, etc... in it? I ask because when I try them I get a has no method errors for each of them with regards to a Date object?
Second question is: is there a resource I have missed on how to deal with dates in Node/V8 that I have just missed somewhere?
At the end of the day I am trying to get a date object that is from an hour ago and an hour into the future. Also 5 minutes ago and 5 minutes in the future. It doesn't seem like it should be that hard, but I have been spinning my wheels for a couple of hours now.
Also do it without a 3rd party javascript module.
Here is one, of many, attempt with little luck:
var d1 = Date();
console.log(d1);
console.log(d1.getMonth());
error:
TypeError: Object Sun May 13 2012 20:28:01 GMT-0500 (CDT) has no method 'getMonth'
Another example this time from REPL: (Should this not be "march 3 2012 at 3:03:03")?
d1 = new Date(2012,3,3,3,3,3)
> Tue, 03 Apr 2012 08:03:03 GMT
When the Date constructor is called as a function, it returns a string, not a date object. Change your code to:
var d1 = new Date();
I'm working on JavaScript and stuck in a small issue.
I am receiving this date in JSON response 1322919399447-0500
and I want to format this like: 6:50 PM, Dec 3rd 2011.
I'm not sure if this is the best way (I'm sure it's not, actually), but essentially you can make that datestring into a js Date object, then pull out the pieces to manipulate as you see fit:
var dateThing = new Date(1322919399447-0500);
dateThing.getFullYear(); // 2011
dateThing.getDay(); // 6
dateThing.getDate(); // 3
dateThing.getMonth(); // 11
dateThing.getHours(); // 8 (test for anything over 12, that indicates PM)
dateThing.getMinutes(); // 36
Then you can concatenate those pieces into your own format. Like I said, there's probably a better way, but this works in a pinch.
I used this handy little date format addon and it worked very well for me. Even took care of the pesky internet explorer quirks with the month.
This is a similar date format function I created that uses the same flags that PHP's date function uses.
PHP date function in Javascript
Here is the snippet with your example input. It is using script linked by Zoidberg.
This code returns formatted UTC date. If you want your local date then remove UTC: from the return statement.
function convertTime(dateString) {
// get ms part from the string
var milis = +dateString.substring(0, 13);
// get timezone part as "# of hours from UTC", e.g. "-0500" -> -5
var offset = +dateString.substring(13, 16);
// move the time for "offset" number of hours (to UTC time)
var date = new Date(milis - offset * 3600000);
// using http://stevenlevithan.com/assets/misc/date.format.js
return date.format("UTC:h:MM TT, mmm dS yyyy");
}
EDIT: Changed + offset * to - offset * as we want to normalize to UTC.