Prevent toIsoString to change day - javascript

When I do this:
new Date('4/7/2018').toISOString();
I get: "2018-04-06T22:00:00.000Z"
How can I get an ISO string but without the date changing from 7 to 6? I basically want the same date, month and year.

Use 2018Z in your year field:
var res = new Date('4/7/2018Z').toISOString();
console.log(res);

I think this is to do with the locale of the machine (i.e you're on gmt+2 so 4/7/2018 at 00:00:00 is indeed 2018-04-06T22:00:00.000Z)
You could do new Date('4/7/2018 GMT').toISOString();

Date strings do not have a timezone. Using the built-in parser for any format other than the one specified in ECMA-262 (a limited subset of ISO 8601) is implementation dependent and should not be used, see Why does Date.parse give incorrect results?
A couple of options are to parse the string as UTC values and then use toISOString and remove the trailing Z, or you can just reformat the string, e.g.
var s = '4/7/2018';
// Parse string in m/d/y format and return
// in ISO 8601 format
function parseDMY(s) {
var b = s.split(/\D/);
return new Date(Date.UTC(b[2],b[0]-1,b[1])).toISOString().slice(0,19);
}
console.log(parseDMY(s));
function reformatDate(s) {
var b = s.split(/\D/);
function z(n){return (n<10?'0':'')+n};
return `${b[2]}-${z(b[0])}-${z(b[1])}T00:00:00`;
}
console.log(reformatDate(s));
But really, if you just have a date, it should be left as just a date, so:
var s = '4/7/2018';
// Assume date is M/D/Y
function reformatDate(s) {
var a = s.split(/\D/).map(n=>(n<10?'0':'')+n);
return a[2]+'-'+a[0]+'-'+a[1];
}
console.log(reformatDate(s));

Related

Convert Epoch timestamp to ISO in javascript

I have a function in Java to convert an Epoch date to ISO 8601, but I've come across the need to do it in Javascript. I have it somewhat working in JS but it needs to be localized to the timezone.
Java version:
public static String epochToIso8601(long time, String Zone) {
String format = "yyyy-MM-dd'T'HH:mm:ssX";
TimeZone timeZone = TimeZone.getTimeZone(Zone);
SimpleDateFormat sdf = new SimpleDateFormat(format, Locale.getDefault());
sdf.setTimeZone(timeZone);
return sdf.format(new Date(time));
}
Param1: -157737600000
Param2: PST
Output: 1965-01-01T00:00:00-08
My attempt in Javascript:
function epcov(epoch, timezone)
{
var someValueNum = Number(epoch);
var s = new Date(someValueNum);
return s.toISOString();
}
Essentially I want the same thing that's coming out of Java, but it's outputting: 1965-01-01T08:00:00.000Z
By the way, I'm already splitting the date and time up from something that looks like this, so if there is a better to just pass in the following as one string and let Javascript parse it, that would be amazing:
/Date(-157737600000-0800)/
We can convert the string /Date(-157737600000-0800)/ to a unix time (in ms), and a UTC offset in HHMM using String.match().
The HHMM UTC offset can then be converted to a UTC offset in milliseconds by multiplying the HH value by 3600000 and the MM value by 60000.
We then create a new Date object using the unix time and offset values, since we know the exact offset at that point in time.
We then format using Date.toISOString() and replace the 'Z' UTC offset timezone value with the actual UTC offset string (e.g. '-08:00').
function parseAndFormatDate(date) {
const [,millis, offset] = date.match(/([+\-]+\d+)([+\-]+\d+)/);
const offsetMillis = (offset.slice(0, 1) + '1') * (offset.slice(1, 3) * 3600000 + offset.slice(-2) * 60000);
const formattedOffset = offset.slice(0, 3) + ':' + offset.slice(-2);
return new Date(+millis + offsetMillis).toISOString().replace('Z', formattedOffset);
}
console.log(parseAndFormatDate('/Date(-157737600000-0800)/'));
console.log(parseAndFormatDate('/Date(+1664271413000+0100)/'));
.as-console-wrapper { max-height: 100% !important; }
I hope this helps you in some way.
JS doesn't have good (any?!) support for exporting an ISO 8601 string in a specified time zone. So you have to construct the string yourself, manually.
The use of the Swedish locale is to get an ISO 8601-like basis from which to pull the elements of the date time. Unfortunately there is no ISO 8601 formatting locale.
Note that the following will only reliably work with IANA timezone names because timezone abbreviations (PST, CST, BST) can be ambiguous. For example: V8 will accept 'PST' but SpiderMonkey will not.
// Get wall clock date at the specified tz in IS0 8601
const getISO8601Date = (d, timeZone) =>
d.toLocaleString('sv-SE', { timeZone, dateStyle: 'short'})
// Get wall clock time at the specified tz in IS0 8601
const getISO8601Time = (d, timeZone) =>
d.toLocaleString('sv-SE', { timeZone, timeStyle: 'medium'})
// Get time zone offset in specified tz in IS0 8601
const getISO8601TimeZoneOffset = (d, timeZone) => {
const s = d.toLocaleString('sv-SE', { timeZone, timeZoneName: 'longOffset' })
const result = /GMT(?<offset>[+−]\d\d:\d\d)/.exec(s) // Use regexp to pull out offset
return result ? result.groups.offset : 'Z'
}
// Put together an ISO 8601 string representing the wall clock at the specified date, in the specified timezone
const getISO8601Dtg = (instant, timeZone) => {
const d = new Date(instant)
return `${getISO8601Date(d, timeZone)}T${getISO8601Time(d, timeZone)}${getISO8601TimeZoneOffset(d, timeZone)}`
}
// Only reliably accepts IANA timezone names eg. 'America/Los_Angeles'
console.log(getISO8601Dtg(-157737600000, 'America/Los_Angeles')) // 1965-01-01T00:00:00−08:00
Relevant.

Format existing date variable with moment.js

I have a date variable (coming from an external source):
var date = '28/04/2017';
var time = '19:28';
It is possible to format these variables with moment.js (or without?) to variout formats?
Example: 04.28 19:28, 2017.04.28 19:28 or even Today at 19:28 (with moment().calendar();)
I tried
moment(date+' '+time).format('MM.DD.YYYY');
...but I am getting "Invalid date" error.
You're using moment(String) method, but you're not passing a Supported
format that it expects to parse.
You should use moment(String, String), where the first String is the input date string, and second is the format of your input date String.
Try this:
moment(date+' '+time,'DD/MM/YYYY HH:mm').format('MM.DD.YYYY');
Try:
moment(new Date(date + ' ' + time)).format('MM.DD.YYYY');
You need to keep the same format:
var date = '04-28-2017'; // Month/day/year
var time = '19:28';
console.log( moment(date, 'MM-DD-YYYY').format('MMMM D') ) // April 28

How to subtract two different dates from a date/time stamp?

I need to subtract a date like 1/26/2015 from a date-time like 2016-01-27T01:10:57.569000+00:00. From what I've read converting both to distance in milliseconds from Epoch and then subtracting is the easiest way. I've tried using various methods, but all the methods seem to say 2016-01-27T01:10:57.569000+00:00 is invalid data. The method .getTime() works great for the 1/26/2015 format, but it can't read the 2016-01-27T01:10:57.569000+00:00.
How does one go about getting the date/time UTC time into milliseconds?
On a complicated way you can use a regex to extract each part of the date as string and then use them in a new Date with all parameters:
function getTimeDifference(){
var regEx = /(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):([\d.]+)/;
var dateString = '2016-01-27T01:10:57.569000+00:00';
var r = regEx.exec( dateString );
var date1 = new Date(r[1], r[2]-1, r[3], r[4], r[5], r[6]); // Notice the -1 in the month
var date2 = new Date('1/26/2015');
var difference = date1 - date2;
Logger.log(difference);
}
I ended up using this. When I call parseDate(), I used getTime() to get the date in milliseconds then subtracted them and converted them to days. For my use case the time didn't have to be down to the second, but if it did, it wouldn't be hard to parse more info from the string. I ran into trouble initially because as a beginner Javascript writer I didn't know why apps script wouldn't accept this format into the date constructor.
function parseDate(str) {
//This should accept 'YYYY-MM-DD' OR '2016-01-27T01:10:57.569000+00:00'
if(str.length == 10){
var mdy = str.split('-');
return new Date(mdy[0], mdy[1]-1, mdy[2]);
}
else
{
var mdy = str.split('-');
var time = mdy[2].split('T');
var hms = time[1].split(':');
return new Date(mdy[0], mdy[1]-1, time[0], hms[0], hms [1]);
}
}
If you are confident that the values in the date strings will always be valid and that the ISO8601 string will always have offset 00:00 (i.e. UTC), then simple parse functions are:
// Parse ISO 8601 format 2016-01-27T01:10:57.569000+00:00
function parseISOUTC(s) {
var b = s.split(/\D/);
return new Date(Date.UTC(b[0],b[1]-1,b[2],b[3],b[4],b[5],b[6]));
}
document.write(parseISOUTC('2016-02-04T00:00:00.000+00:00'));
// Parse US format m/d/y
function parseMDY(s) {
var b = s.split(/\D/);
return new Date(b[2],b[0]-1,b[1]);
}
document.write('<br>'+ parseMDY('2/4/2016'))
document.write('<br>'+ (parseISOUTC('2016-02-04T00:00:00.000+00:00') - parseMDY('2/4/2016')))
Note that the first string is UTC and the second will be treated as local (per ECMAScript 2015), so the difference between 2016-02-04T00:00:00.000+00:00 and 2/4/2016 will be the time zone offset of the host system.

Changing date format javascript

I'm pulling some data from two different APIs and I want to the objects later on.
However, I'm getting two different date formats: this format "1427457730" and this format "2015-04-10T09:12:22Z". How can I change the format of one of these so I have the same format to work with?
$.each(object, function(index) {
date = object[index].updated_at;
}
Here's one option:
var timestamp = 1427457730;
var date = new Date(timestamp * 1000); // wants milliseconds, not seconds
var dateString = date.toISOString().replace(/\.\d+Z/, 'Z'); // remove the ms
dateString will now be 2015-03-27T12:02:10Z.
Try moment.js
var timestamp = 1427457730;
var date = '2015-04-10T09:12:22Z';
var m1 = moment(timestamp);
var m2 = moment(date);
console.log(m1);
console.log(m2);
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.11.1/moment.min.js"></script>
You can use .format() method in moment to parse the date to whatever format you want, just like:
m2.format('YYYY MMM DD ddd HH:mm:ss') // 2015 Apr 10 Fri 17:12:22
Check out the docs for more format tokens.
What you probably want in javascript, are date objects.
The first string is seconds since epoch, javascript needs milliseconds, so multiply it by 1000;
The second string is a valid ISO date, so if the string contains a hyphen just pass it into new Date.
var date = returned_date.indexOf('-') !== -1 ? returned_date : returned_date * 1000;
var date_object = new Date(date);
Making both types into date objects, you could even turn that into a handy function
function format_date(date) {
return new Date(date.indexOf('-') !== -1 ? date : date * 1000);
}
FIDDLE
Take a look at http://momentjs.com/. It is THE date/time formatting library for JavaScript - very simple to use, extremely flexible.

Javascript - Convert string to date and compare dates

I have date from the date picker which I am accessing as -
var transdate = $j("input[name='enterdate']").val();
resulting in transdate = "6/22/2015"
I need to test if the entered date is between two dates which are defined as
startdate = '2015-02-01' and enddate = '2015-07-30'
How do I convert the transdate in yyyy-mm-dd format in the following code -
if ((new Date('transdate')>= startdate ) && (new Date('transdate') <= enddate )) {
alert("correct date entered");
}
Moment.js is a small handy library for dates that makes this easy.
moment('6/22/2015', 'M/D/YYYY')
.isBetween('2015-02-01', '2015-07-30'); // => true
Note that only the first (US format) date string needed an explicit format string supplied.
Moment can be useful for the parsing alone, eg. even if not using isBetween:
var transdate = moment('6/22/2015', 'M/D/YYYY').toDate();
var startdate = moment('2015-02-01').toDate();
var enddate = moment('2015-07-30').toDate();
transdate >= startdate && transdate <= enddate // => true
The string is not in the only format defined to be handled by the Date object. That means you have to parse it (with regular expressions or String#split or whatever), or use a library like MomentJS that will parse it for you. Once you've parsed the dates, you can compare them with < or >, etc.
Do not rely on Date to parse strings it's not defined to parse. You will run into implementations or locales where it doesn't work.
"6/22/2015" is trivial to parse with a regular expression:
var rex = /^(\d+)\/(\d+)\/(\d+)$/;
var match = rex.exec(transdate);
var dt = match ? new Date(+match[3], +match[1] - 1, +match[2]) : null;
That uses the Date constructor that accepts the parts of the date as individual numeric arguments (year, month, day). The + converts strings to numbers. The [x] are capture groups from the regex. You have to subtract one from the month because months start with 0 in JavaScript.
Similar questions have been asked many, many times but I can't seem to find a duplicate. Given the unreliability of the Date constructor to parse strings, the simplest solution is to parse the string yourself:
function parseMDY(s) {
var b = s.split(/\D/);
return new Date(b[2], b[0]-1, b[1]);
}
Here is the JSFIDDLE of you output.
Moment.js will give you good flexibility in coding.
Dont forget to add jquery and moment.js in your html
var transdate="6/22/2014";
var convertStringToValidDate = new Date(transdate);
$(document).ready(function(){
$("#selectedDate").text(transdate);
$("#validDate").text(convertStringToValidDate);
converttoformat = moment(convertStringToValidDate).format("YYYY-MM-DD");
$("#converttoyyyymmdd").text(converttoformat);
if(moment(converttoformat).isBetween('2015-02-01', '2015-07-30')){
$("#result").text("Date lies in between");
}
else{
$("#result").text("Date is out of scope");
}
});

Categories