I'm working on a project where I'm given the Microsoft date/time format, which seems to be exactly like a standard ISO formatting.
When I try to format a date with Moment.js, it doesn't come out right. For example, the format I'm provided with has 'yy' for the 2-digit year and 'd' for a 1-digit day-of-month.
When I look at the Moment.js format documentation I realize the it doesn't even support it? That's a bit odd? Why would it not support a standard?
Or am I doing something wrong? Am I missing something?
I'd really hate to try to write an ISO to Moment.js format converter.
Has anyone had the same problems? If so, how have you resolved this?
Update 2017.10.16 17:32:
After getting a good question from Matt Johnson down in the comment, I read my post again and realized I've been working for so long in this "embedded" web project that I probably wasn't quite clear as to what is meant by "windows giving me a date format". So I wrote the following in response to his question:
#MattJohnson, what I mean is that the web project I'm working on for a client is an IE embedded (OLE) inside a Windows application (compiled binary, not web). The JavaScript portion of the web application "talks" to the desktop application in order to receive/send data. One of the data I receive is a "dateFormat" and "timeFormat" property. The values I receive, I'm told come directly from the Windows machine (based on user configuration of that OS). It happens that years/days are all lowercase, causing Moment.js to not being able to format dates properly. Thus the conversion I now have.
Examples:
Calling
moment().format();
Will produce
"2017-10-13T13:24:47-04:00"
Now, if I want to format it according to the Moment.js documentation, I'd do this:
moment().format('MM/DD/YYYY');
To get this:
"10/13/2017"
The problem is that Windows passes along this format:
"dd/MM/yyyy"
So when I call Moment with it, like:
moment().format('dd/MM/yyyy');
Giving me this:
"Ve/30/yyyy"
While I was expecting this:
13/10/2017
When I look at many other date formatting libraries, I see that they all support the 'yyyy', 'dd' and 'MM' structure. But not Moment.js.
Update 2017.10.13 16:41:
I did a comparison of Microsoft's date/time format to that of Moment.js and saw the differences.
* ---------------------------------------------------------------------------------------------
* Unit Microsoft Examples Moment.js Differnces?
* ---------------------------------------------------------------------------------------------
* day d, dd 1, 01 D, DD Yes, case
* day of week ddd, dddd Fri, Friday ddd, dddd None
* month M, MM, MMM, MMMM 8, 08, Oct., October M, MM, MMM, MMMM None
* year yy, yyyy 17, 2017 YY, YYYY Yes, case
*
* hour h, hh, H, HH 3, 03, 15, 15 h, hh, H, HH None
* minutes m, mm 9, 09 m, mm None
* seconds s, ss 5, 05 s, ss None
*/
Using that information, I quickly wrote a format conversion function:
function windowsFormatToMomentJSFormat(windowsFormat) {
var format = windowsFormat;
console.log("Converting date format...");
if (!windowsFormat) return format;
console.log(" > From : '" + windowsFormat + "'");
format = format.replace(/y/g, 'Y'); // Fix case for years
format = format.replace(/d{4}/g, '#'); // Protect 4-digit DOW sequence
format = format.replace(/d{3}/g, '&'); // Protect 3-digit DOW sequence
format = format.replace(/d/g, 'D'); // Fix case for days
format = format.replace(/#/g, 'dddd'); // Restore our sequence
format = format.replace(/&/g, 'ddd'); // Restore our sequence
console.log(" > To : '" + format + "'");
console.log(" > Applied : '" + moment().format(format) + "'");
return format;
}
It seems to work well, although I wish I was much better at advanced REGEX in order optimize the function and remove the protect/restore code.
So now, my Windows format strings seems to be processed correctly by Moment.js' format() function.
Yes, you will need a conversion function, because date/time formatting tokens are different across various libraries and platforms. There isn't one already developed, that I am aware of.
This is the list of formatting tokens supported in Moment
This is the list of formatting tokens supported in .NET, which is roughly the same as the ones used in the Windows date/time region settings.
Here is a moment plugin that does almost what you want, but it uses Java's token set, not Windows. You could base your implementation on that.
Note that your current function is missing several tokens. In particular the am/pm separator needs translation, and you should think about literals and escape sequences as well.
Related
I get two separate time and date values from my API.
date: 20190404
time: 09:30
I want to combine the two in one acceptable format, such as YYYY-MM-DDThh:mm:ss.
I have tried the following:
moment(data[i].date + 'T' + data[i].time).valueOf()
but I get the following error in the console:
Deprecation warning: value provided is not in a recognized RFC2822 or ISO format. moment construction falls back to js Date(), which is not reliable across all browsers and versions. Non RFC2822/ISO date formats are discouraged and will be removed in an upcoming major release. Please refer to http://momentjs.com/guides/#/warnings/js-date/ for more info.
and the value in my array shows as 'NaN'
Thanks!
Concatenate the date and time without space and add the format as the second parameter of moment()
var moment = require("moment")
var data = {date: '20190404',
time: '09:30'}
var joined = `${data.date}${data.time}`
console.log(moment(joined, 'YYYYMMDDh:mm:ss').format())
// "2019-04-04T09:30:00+01:00"
I am just printing the ISO datetime with timezone as per the below documentation
http://support.sas.com/documentation/cdl/en/lrdict/64316/HTML/default/viewer.htm#a003169814.htm
This is my code
TimeZone tz = TimeZone.getTimeZone("UTC");
DateFormat df = new SimpleDateFormat("yyyy-mm-dd'T'hh:mm:ss.nnnnnn+|-hh:mm");
df.setTimeZone(tz);
dateTimeWithTimeZone = df.format(new Date());
However i am getting this exception
Illegal pattern character 'n'
I cant use this format directly in Java ?
java.time
dateTimeWithTimeZone = Instant.now().toString();
System.out.println(dateTimeWithTimeZone);
When I ran this snippet just now, I got this output:
2019-03-18T22:28:13.549319Z
It’s not clear from the page you link to, but it’s an ISO 8601 string in UTC, so should be all that you need. I am taking advantage of the fact that the classes of java.time produce ISO 8601 output from their toString methods. The linked page does show the format with hyphens, T and colons (2008-09-15T15:53:00+05:00), it shows another example with decimals on the seconds (15:53:00.322348) and a third one with Z meaning UTC (20080915T155300Z), so I would expect that the combination of all three of these would be OK too.
The format you used in the quesiton seems to try to get the offset as +00:00 rather than Z. If this is a requirement, it’s only a little bit more complicated. We are using an explicit formatter to control the variations within ISO 8601:
DateTimeFormatter iso8601Formatter
= DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSSSSSxxx");
dateTimeWithTimeZone = OffsetDateTime.now(ZoneOffset.UTC).format(iso8601Formatter);
System.out.println(dateTimeWithTimeZone);
2019-03-18T22:28:13.729711+00:00
What went wrong in your code?
You tried to use the formatting symbols from your source with SimpleDateFormat. First, you should never, and especially not in Java 8 or later, want to use SimpleDateFormat. That class is notoriously troublesome and long outdated. Second, some of its format pattern letters agree with the symbols from your source, some of them don’t, so you cannot just use the symvol string from there. Instead you need to read the documentation and find the correct format pattern letters to use for year, month, etc. And be aware that they are case sensitive: MM and mm are different.
Link
Oracle Tutorial: Date Time
explaining how to use java.time.
I've read thru various posts on here in regards to similiar issues but none have solved my problem.
I manipulate the moment.js date object, and then store it as timestamp.
BUT, when I try to read in that timestamp again, I get that deprecated warning.
""Deprecation warning: moment construction falls back to js Date. This is discouraged and will be removed in upcoming major release. Please refer to https://github.com/moment/moment/issues/1407 for more info."
I've tried toDate(), format(), moment(myTimeStamp, 'ddd, DD MMM YYYY HH:mm:ss ZZ'); --> all generate the warning...
So, for example, my timestamp will look like this:
const timestamp = '1458586740000'
when I read that back and try to parse out the month/day/year, then the hour/min am/pm, etc... I need to get that timestamp into a moment.js object. Nothing is working for me. Any ideas.
How can I get this timestamp: '1458586740000', into a moment.js object so I can extract date date from it as I need?
EDIT: this is how I am storing the timestamp. So I would need to retrieve it from this.
let timeStamp = Moment(state[_Date])
.add({ hour: state[AMPM] === 'PM'
? +state[Hour] + 12
: state[Hour] ,
minute: state[Min] }).format('x')
The X token indicates a unix timestamp in seconds, and the x token indicates a unix millisecond timestamp (offset).
You appear to have a millisecond timestamp, so you would make a moment out of it by doing the following:
var a = moment('1458586740000', 'x')
It works without ' as well:
var a = moment(1458586740000, 'x')
You can also not specify the x and it should work:
moment(1458586740000)
Because you have a unix offset (milliseconds), not a unix timestamp (seconds), moment.unix is not what you want.
Then you can do the following:
a.format()
"2016-03-21T13:59:00-05:00"
Or you can use any of the other formatting tokens listed here to output whatever result you would like: http://momentjs.com/docs/#/displaying/format/
Based on the code you presented, I think you may be having problems because your timestamp is stored as a string (in ''). Parsing as a string causes an invalid date error, because it attempts to match ISO 8601 format and fails. Specifying that 'x' token will cause it to assume unix offset and work correctly.
Right now I'm trying to parse a date that's written in a human-readable format into a DateTime String that a SharePoint list will accept. In order to do this I've determined that I need a String in a format similar to ISO that looks like: 2007-08-20T00:00:00Z. It seems that SharePoint only accepts DateTimes that are in UTC with no milliseconds included (for whatever reason, SharePoint gives errors and won't accept the DateTime when you include the milliseconds), so I need to convert my local time into a UTC time before converting it to the ISO string.
Here's the process that the code below is using.
First I use DateJS to parse my human-date into a JavaScript Date.
(Works fine, but apparently DateJS has been abandoned, so maybe I
should change this to use MomentJS.)
Next I tried to create a new
moment in UTC. (This line is very, very wrong, and crashes my
program.)
Then I have SPServices convert it into an ISO. SPServices drops the milliseconds off the DateTime so that SharePoint will accept it. (Works
fine).
I'm sure there has to be a more elegant/working way to achieve this, instead of stitching together 3 different libraries. I'm just not sure what it is.
var jScriptStartDate = Date.parse("6/29/2014 8:30am"); //JS Date
var jScriptStartDateUTC = moment(jScriptStartDate).utc(); //local date to UTC.
var startDate = $().SPServices.SPConvertDateToISO({ //Sharepoint ISO 8601 format
dateToConvert: jScriptStartDateUTC,
dateOffset: "" //Sharepoint dates only accept UTC times, aka no dateOffset.
});
newItem.set_item('EventDate', startDate); //EventDate is internal for StartTime
You can just use moment.js, and this is all in the documentation.
moment('6/29/2014 8:30am','M/D/YYYY h:mma').toISOString()
This assumes all of the following:
The source value is in the user's time zone (that is - the time zone of the machine where the JavaScript code is running)
The input will always be in the specified format
It's also worth mentioning that if you put a space before the "am", that most modern browsers can do this natively without any library:
new Date('6/29/2014 8:30 am').toISOString()
If you take that approach, realize that the date parts are ordered according to the users locale, which might be m/d/y, or d/m/y or y/m/d.
Also, you said in the title "... with no milliseconds", but didn't elaborate on that in your question. I'm fairly certain you can pass the milliseconds without issue. There's no good reason to go out of your way to remove them. But if you must, then that would be like this with moment:
moment('6/29/2014 8:30am','M/D/YYYY h:mma').utc().format('YYYY-MM-DD[T]HH:mm:ss[Z]')
I ended up adjusting this code to use the updated DateJS (https://github.com/abritinthebay/datejs/) and a custom function I made called .toShortISOString().
The process is down to 3 lines:
var jScriptStartDate = Date.parse("6/28/2014 8:00am"); //convert to Javascript Date
var startDate = jScriptStartDate.toShortISOString(); //convert to Sharepoint ISO format (UTC with no milliseconds)
newItem.set_item('EventDate', startDate); //Strangely the internal name for Start Time is EventDate
.toShortISOString()'s main change is the removal of milliseconds, since SharePoint doesn't like milliseconds. It's code looks like this inside of the date.js file:
if ( !$P.toShortISOString ) {
$P.toShortISOString = function() {
return this.getUTCFullYear() +
"-" + p(this.getUTCMonth() + 1) +
"-" + p(this.getUTCDate()) +
"T" + p(this.getUTCHours()) +
":" + p(this.getUTCMinutes()) +
":" + p(this.getUTCSeconds()) +
//Remove the milliseconds.
//"." + String( (this.getUTCMilliseconds()/1000).toFixed(3)).slice(2, 5) +
"Z";
};
}
If you're trying to add this to date.js, make sure you have the latest version from the link above, then search the file for toISOString and place the code right below the handler for toISOString.
I am using ColdFusion 10 to make some REST calls and the date returned is using a GMT offset.
Example: 2013-03-25T14:30:40-04:00
I need this formatted for 2 purposes:
Screen Display so it looks something like mm/dd/yyyy hh:mm:ss
To Insert into mySQL.
I have tried a variety of the CF time/date functions but continue to get the "is not a valid date format"
I thought maybe the #ParseDateTime(i.submitted_at,"pop")# would handle it with POP but same issue.
Spent a few hours now trying multiple variations and googling around now just going in circles. Any ideas would be greatly appreciated.
Thanks!
Have a look at the UDF DateConvertISO8601() on CFLib.
DateConvertISO8601(ISO8601dateString, targetZoneOffset) on CFLib
Description:
This function take a string that holds a date in ISO 8601 and converts it to ODBC datetime, but could be adapted to convert to whatever you like. It also will convert to a datetime in a timezone of your choice by specifying the offset, i.e. it could take a datetime in GMT and convert to PT. See http://www.w3.org/TR/NOTE-datetime for description of ISO 8601, the International Standard for the representation of dates and times.
Return Values:
Returns a datetime.
The source code is viewable at the link I provided.
This, 2013-03-25T14:30:40-04:00, is a string. If you run this:
x = left(2013-03-25T14:30:40-04:00, 19);
you get 2013-03-25T14:30:40. You can use the replace function to replace the T with a space. You can then to this
DateTimeVar =parsedatetime('2013-03-25 14:30:40');
Now you have a datetime variable that you can format. If necessary you can do a datediff with the offset from GMT.
This is an informational answer, not a direct answer to the question.
ColdFusion 11 has updated the ParseDateTime() function so that it will correctly convert the ISO-8601 date/time strings to a ColdFusion datetime object.
With a number of remote requests and responses, the date / time values can often be returned in ISO format. In your case, the mask looks like this:
YYYY-MM-DDThh:mm:ssTZD (eg 1997-07-16T19:20:30+01:00)
In this ISO format, the T string is a literal representation of a marker where the time stamp starts in the string (with the offset following directly).
Below is a reusable function that will convert an ISO date format into a useable ColdFusion date time object:
<cffunction name="ISOToDateTime" access="public" returntype="string" output="false"
hint="Converts an ISO 8601 date/time stamp with optional dashes to a ColdFusion
date/time stamp.">
<cfargument name="Date" type="string" required="true" hint="ISO 8601 date/time stamp." />
<cfreturn ARGUMENTS.Date.ReplaceFirst(
"^.*?(\d{4})-?(\d{2})-?(\d{2})T([\d:]+).*$",
"$1-$2-$3 $4"
) />
</cffunction>
You can then call the function like so to output or return a ColdFusion-friendly version of the date time:
ISOToDateTime( "2013-03-25T14:30:40-04:00" )
That function is courtesy of Ben Nadel. The original blog post can be found here:
http://www.bennadel.com/blog/811-Converting-ISO-Date-Time-To-ColdFusion-Date-Time.htm
You can also convert the date time value using the offset, if required. Again, Ben Nadel has a great blog post outlining how to accomplish this:
http://www.bennadel.com/blog/1595-Converting-To-GMT-And-From-GMT-In-ColdFusion-For-Use-With-HTTP-Time-Stamps.htm
CF10 can use this code as stated in the example of the parseDateTime() doc.
<cfset string = "1997-07-16T19:20:30+01:00">
<cfset date = parseDateTime(string, "yyyy-MM-dd'T'HH:mm:ssX")>