I have a map of data:
{
name: name,
time: <epoch in seconds>,
}
My goal is to create 6 documents with this data in Firestore, but with each document, the time field should be incremented by 1 week. So if my initial time is Sun Nov 17 2019 in epoch, there should be 6 documents with time (as Firestore timestamp) Sun Nov 17 2019, Sun Nov 24 2019, Sun Dec 1 2019, etc.
I'm using a https cloud function and tried doing this:
var name = 'test';
var time = 1573992000; // 7 AM EST on Sun, Nov 17 2019
var data = {
name: name,
time: time,
};
var start = new Date(time * 1000); // convert to milliseconds
var i;
for (i = 0; i < 6; i++) {
var ref = db.collection('shifts').doc();
start.setDate(new Date(start) + 7);
data['time'] = new admin.firestore.Timestamp(start.getTime() / 1000, 0);
batch.set(ref, data);
}
return batch.commit();
But all the documents appear in firestore with the same time (6 weeks after the initial). My guess is that it's something with the batch only setting the latest value. How can I avoid this without having to create 6 separate maps?
You usage of Date looks overall incorrect to me.
setDate() sets the date of the month to the exact value, and it will not increment the month if needed to accommadate values that go beyond what the month allows (that is to say, if you pass 32, no month would ever accept that).
Also this doesn't make sense to me: new Date(start) + 7. You can't simply add 7 to a date object. It looks like maybe you meant to add 7 to the date of the month represented in the date. But again, that won't work the way you expect if the value is too high for the given month.
All things considered, the Date object isn't going to help you out too much here. I suggest just doing date math on integer numbers. For example, if your start time is:
var time = 1573992000
You can add 7 days worth of seconds to it like this:
time + (7 * 24 * 60 * 60)
This should be easier to work with.
I am creating a datetime string that looks like this: 2010-07-15 11:54:21
And with the following code I get invalid date in Firefox but works just fine in Chrome
var todayDateTime = year + '-' + month + '-' + day + ' ' + hour + ':' + minute + ':' + seconds;
var date1 = new Date(todayDateTime);
In firefox date1 is giving me an invalid date, but in chrome its working just fine what would the main cause be?
You can't instantiate a date object any way you want. It has to be in a specific way. Here are some valid examples:
new Date() // current date and time
new Date(milliseconds) //milliseconds since 1970/01/01
new Date(dateString)
new Date(year, month, day, hours, minutes, seconds, milliseconds)
or
d1 = new Date("October 13, 1975 11:13:00")
d2 = new Date(79,5,24)
d3 = new Date(79,5,24,11,33,0)
Chrome must just be more flexible.
Source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date
From apsillers comment:
the EMCAScript specification requires exactly one date format (i.e., YYYY-MM-DDTHH:mm:ss.sssZ) but custom date formats may be freely supported by an implementation: "If the String does not conform to that [ECMAScript-defined] format the function may fall back to any implementation-specific heuristics or implementation-specific date formats." Chrome and FF simply have different "implementation-specific date formats."
This works in all browsers -
new Date('2001/01/31 12:00:00 AM')
new Date('2001-01-31 12:00:00')
Format: YYYY-MM-DDTHH:mm:ss.sss
Details: http://www.ecma-international.org/ecma-262/5.1/#sec-15.9.1.15
Option 1 :
Suppose your timestring has a format that looks like this :
'2016-03-10 16:00:00.0'
In that case, you could do a simple regex to convert it to ISO 8601 :
'2016-03-10 16:00:00.0'.replace(/ /g,'T')
This would procude the following output :
'2016-03-10T16:00:00.0'
This is the standard datetime format, and thus supported by all browsers :
document.body.innerHTML = new Date('2016-03-10T16:00:00.0') // THIS IS SAFE TO USE
Option 2 :
Suppose your timestring has a format that looks like this :
'02-24-2015 09:22:21 PM'
Here, you can do the following regex :
'02-24-2015 09:22:21 PM'.replace(/-/g,'/');
This, too, produces a format supported by all browsers :
document.body.innerHTML = new Date('02/24/2015 09:22:21 PM') // THIS IS SAFE TO USE
Option 3 :
Suppose you have a time string that isn't easy to adjust to one of the well-supported standards.
In that case, it's best to just split your time string into different pieces and use them as individual parameters for Date :
document.body.innerHTML = new Date(2016, 2, 26, 3, 24, 0); // THIS IS SAFE TO USE
This works in most browsers as well
new Date('2001/01/31 12:00:00')
That is the format of
"yyyy/MM/dd HH:mm:ss"
If you still want to create date using dashes, you can use this format:
var date = new Date('2013-08-31T17:00:00Z')
But bear in mind, that it creates time according to UTC. Meaning, if you live in GMT+3 (3 hours ahead of GMT) timezone, it will add this timezone offset to the time. So the above example will have this value, if GMT+3 (note that it is hour 20:00 and not 17:00):
Sat Aug 31 2013 20:00:00 GMT+0300 (FLE Standard Time)
Be sure to add 'Z' letter at the end, because otherwise Chrome and Firefox will parse the string differently (one will add time offset and the other won't).
I was having a similar issue in both Firefox and Safari when working with AngularJS. For example, if a date returned from Angular looked like this:
2014-06-02 10:28:00
using this code:
new Date('2014-06-02 10:28:00').toISOString();
returns an invalid date error in Firefox and Safari. However in Chrome it works fine. As another answer stated, Chrome is most likely just more flexible with parsing date strings.
My eventual goal was to format the date a certain way. I found an excellent library that handled both the cross browser compatibility issue and the date formatting issue. The library is called moment.js.
Using this library the following code works correctly across all browsers I tested:
moment('2014-06-02 10:28:00').format('MMM d YY')
If you are willing to include this extra library into your app you can more easily build your date string while avoiding possible browser compatibility issues. As a bonus you will have a good way to easily format, add, subtract, etc dates if needed.
This should work for you:
var date1 = new Date(year, month, day, hour, minute, seconds);
I had to create date form a string so I have done it like this:
var d = '2013-07-20 16:57:27';
var date1 = new Date(d.substr(0, 4), d.substr(5, 2), d.substr(8, 2), d.substr(11, 2), d.substr(14, 2), d.substr(17, 2));
Remember that the months in javascript are from 0 to 11, so you should reduce the month value by 1, like this:
var d = '2013-07-20 16:57:27';
var date1 = new Date(d.substr(0, 4), d.substr(5, 2) - 1, d.substr(8, 2), d.substr(11, 2), d.substr(14, 2), d.substr(17, 2));
Simple Solution, This works with All Browsers,
var StringDate = "24-11-2017"
var DateVar = StringDate.split("-");
var DateVal = new Date(DateVar[1] + "/" + DateVar[0] + "/" + DateVar[2]);
alert(DateVal);
One situation I've run into was when dealing with milliseconds. FF and IE will not parse this date string correctly when trying to create a new date.
"2014/11/24 17:38:20.177Z"
They do not know how to handle .177Z. Chrome will work though.
This is what worked for me on Firefox and Chrome:
// The format is 'year-month-date hr:mins:seconds.milliseconds'
const d = new Date('2020-1-4 12:00:00.999')
// we use the `.` separator between seconds and milliseconds.
Good Luck...
There is a W3C specification defining possible date strings that should be parseable by any browser (including Firefox and Safari):
Year:
YYYY (e.g., 1997)
Year and month:
YYYY-MM (e.g., 1997-07)
Complete date:
YYYY-MM-DD (e.g., 1997-07-16)
Complete date plus hours and minutes:
YYYY-MM-DDThh:mmTZD (e.g., 1997-07-16T19:20+01:00)
Complete date plus hours, minutes and seconds:
YYYY-MM-DDThh:mm:ssTZD (e.g., 1997-07-16T19:20:30+01:00)
Complete date plus hours, minutes, seconds and a decimal fraction of a
second
YYYY-MM-DDThh:mm:ss.sTZD (e.g., 1997-07-16T19:20:30.45+01:00)
where
YYYY = four-digit year
MM = two-digit month (01=January, etc.)
DD = two-digit day of month (01 through 31)
hh = two digits of hour (00 through 23) (am/pm NOT allowed)
mm = two digits of minute (00 through 59)
ss = two digits of second (00 through 59)
s = one or more digits representing a decimal fraction of a second
TZD = time zone designator (Z or +hh:mm or -hh:mm)
According to YYYY-MM-DDThh:mmTZD, the example 2010-07-15 11:54:21 has to be converted to either 2010-07-15T11:54:21Z or 2010-07-15T11:54:21+02:00 (or with any other timezone).
Here is a short example showing the results of each variant:
const oldDateString = '2010-07-15 11:54:21'
const newDateStringWithoutTZD = '2010-07-15T11:54:21Z'
const newDateStringWithTZD = '2010-07-15T11:54:21+02:00'
document.getElementById('oldDateString').innerHTML = (new Date(oldDateString)).toString()
document.getElementById('newDateStringWithoutTZD').innerHTML = (new Date(newDateStringWithoutTZD)).toString()
document.getElementById('newDateStringWithTZD').innerHTML = (new Date(newDateStringWithTZD)).toString()
div {
padding: 10px;
}
<div>
<strong>Old Date String</strong>
<br>
<span id="oldDateString"></span>
</div>
<div>
<strong>New Date String (without Timezone)</strong>
<br>
<span id="newDateStringWithoutTZD"></span>
</div>
<div>
<strong>New Date String (with Timezone)</strong>
<br>
<span id="newDateStringWithTZD"></span>
</div>
In fact, Chrome is more flexible to deal with different string format. Even if you don't figure out its String format, Chrome still can successfully convert String to Date without error. Like this:
var outputDate = new Date(Date.parse(inputString));
But for Firefox and Safari, things become more complex. In fact, in Firefox's document, it already says: (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse)
A string representing an RFC2822 or ISO 8601 date (other formats may be used, but results may be unexpected).
So, when you want to use Date.parse in Firefox and Safari, you should be careful. For me, I use a trick method to deal with it. (Note: it might be not always correct for all cases)
if (input.indexOf("UTC") != -1) {
var tempInput = inputString.substr(0, 10) + "T" + inputString.substr(11, 8) + "Z";
date = new Date(Date.parse(tempInput));
}
Here it converts 2013-08-08 11:52:18 UTC to 2013-08-08T11:52:18Z first, and then its format is fit words in Firefox's document. At this time, Date.parse will be always right in any browser.
In Firefox, any invalid Date is returned as a Date object as Date 1899-11-29T19:00:00.000Z, therefore check if browser is Firefox then get Date object of string "1899-11-29T19:00:00.000Z".getDate(). Finally compare it with the date.
I have used following date format and it's working in all browser.
var target_date = new Date("Jul 17, 2015 16:55:22").getTime();
var days, hours, minutes, seconds;
var countdown = document.getElementById("countdown");
remaining = setInterval(function () {
var current_date = new Date().getTime();
var seconds_left = (target_date - current_date) / 1000;
days = parseInt(seconds_left / 86400);
seconds_left = seconds_left % 86400;
hours = parseInt(seconds_left / 3600);
seconds_left = seconds_left % 3600;
minutes = parseInt(seconds_left / 60);
seconds = parseInt(seconds_left % 60);
countdown.innerHTML = "<b>"+days + " day, " + hours + " hour, "
+ minutes + " minute, " + seconds + " second.</b>";
}, 1000);
I came across this codepen https://codepen.io/donovanh/pen/JWdyEm, and I was trying to apply it to an older countdown timer I did because this one seemed better.. If I set the countdown date to today then it still says there is 30 days left.
Here is the code where it calculates the difference between dates.
function daysBetween( date1, date2 ) {
//Get 1 day in milliseconds
var one_day=1000*60*60*24;
// Convert both dates to milliseconds
var date1_ms = date1.getTime();
var date2_ms = date2.getTime();
// Calculate the difference in milliseconds
var difference_ms = date2_ms - date1_ms;
// Convert back to days and return
return Math.round(difference_ms/one_day);
}
console.log("Days to end of April = " +
daysBetween(new Date(), new Date("2018-04-30")));
I cannot figure out where the extra days are coming from, any help would be appreciated, thanks
I think that your problem comes from giving wrong month number as argument to Date.UTC. According to docs https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/UTC, month is a 0-11 number. If you would like to call function for todays date, you have to call it like new Date(2018, 3, 10, 12, 15).
Months start from 0 and go to 11.
The end of April is Date("2018-03-30"), not Date("2018-04-30") that is why you get extra 30 or 31 days
I am trying to subtract hours from a given date time string using javascript.
My code is like:
var cbTime = new Date();
cbTime = selectedTime.setHours(-5.5);
Where selectedTime is the given time (time that i pass as parameter).
So suppose selectedTime is Tue Sep 16 19:15:16 UTC+0530 2014
Ans I get is : 1410875116995
I want answer in datetime format.
Am I doing something wrong here? Or there is some other solution?
The reason is that setHours(), setMinutes(), etc, take an Integer as a parameter. From the docs:
...
The setMinutes() method sets the minutes for a specified date
according to local time.
...
Parameters:
An integer between 0 and 59, representing the minutes.
So, you could do this:
var selectedTime = new Date(),
cbTime = new Date();
cbTime.setHours(selectedTime.getHours() - 5);
cbTime.setMinutes(selectedTime.getMinutes() - 30);
document.write('cbTime: ' + cbTime);
document.write('<br>');
document.write('selectedTime: ' + selectedTime);
Well first off setting the hours to -5.5 is nonsensical, the code will truncate to an integer (-5) and then take that as "five hours before midnight", which is 7PM yesterday.
Second, setHours (and other functions like it) modify the Date object (try console.log(cbTime)) and return the timestamp (number of milliseconds since the epoch).
You should not rely on the output format of the browser converting the Date object to a string for you, and should instead use get*() functions to format it yourself.
According to this:
http://www.w3schools.com/jsref/jsref_sethours.asp
You'll get "Milliseconds between the date object and midnight January 1 1970" as a return value of setHours.
Perhaps you're looking for this:
http://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_sethours3
Edit:
If you want to subtract 5.5 hours, first you have to subtract 5 hours, then 30 minutes. Optionally you can convert 5.5 hours to 330 minutes and subtract them like this:
var d = new Date();
d.setMinutes(d.getMinutes() - 330);
document.getElementById("demo").innerHTML = d;
Use:
var cbTime = new Date();
cbTime.setHours(cbTime.getHours() - 5.5)
cbTime.toLocaleString();
try this:
var cbTime = new Date();
cbTime.setHours(cbTime.getHours() - 5.5)
cbTime.toLocaleString();
I am trying to create a simple script that gives me the next recycling date based on a biweekly schedule starting on Wed Jul 6, 2011. So I've created this simple function...
function getNextDate(startDate) {
if (today <= startDate) {
return startDate;
}
// calculate the day since the start date.
var totalDays = Math.ceil((today.getTime()-startDate.getTime())/(one_day));
// check to see if this day falls on a recycle day
var bumpDays = totalDays%14; // mod 14 -- pickup up every 14 days...
// pickup is today
if (bumpDays == 0) {
return today;
}
// return the closest day which is in 14 days, less the # of days since the last
// pick up..
var ms = today.getTime() + ((14- bumpDays) * one_day);
return new Date(ms);
}
and can call it like...
var today=new Date();
var one_day=1000*60*60*24; // one day in milliseconds
var nextDate = getNextDate(new Date(2011,06,06));
so far so good... but when I project "today" to 10/27/2011, I get Tuesday 11/8/2011 as the next date instead of Wednesday 11/9/2011... In fact every day from now thru 10/26/2011 projects the correct pick-up... and every date from 10/27/2011 thru 2/28/2012 projects the Tuesday and not the Wednesday. And then every date from 2/29/2012 (leap year) thru 10/24/2012 (hmmm October again) projects the Wednesday correctly. What am I missing? Any help would be greatly appreciated..
V
The easiest way to do this is update the Date object using setDate. As the comments for this answer indicate this isn't officially part of the spec, but it is supported on all major browsers.
You should NEVER update a different Date object than the one you did the original getDate call on.
Sample implementation:
var incrementDate = function (date, amount) {
var tmpDate = new Date(date);
tmpDate.setDate(tmpDate.getDate() + amount)
return tmpDate;
};
If you're trying to increment a date, please use this function. It will accept both positive and negative values. It also guarantees that the used date objects isn't changed. This should prevent any error which can occur if you don't expect the update to change the value of the object.
Incorrect usage:
var startDate = new Date('2013-11-01T11:00:00');
var a = new Date();
a.setDate(startDate.getDate() + 14)
This will update the "date" value for startDate with 14 days based on the value of a. Because the value of a is not the same is the previously defined startDate it's possible to get a wrong value.
Expanding on Exellian's answer, if you want to calculate any period in the future (in my case, for the next pay date), you can do a simple loop:
var today = new Date();
var basePayDate = new Date(2012, 9, 23, 0, 0, 0, 0);
while (basePayDate < today) {
basePayDate.setDate(basePayDate.getDate()+14);
}
var nextPayDate = new Date(basePayDate.getTime());
basePayDate.setDate(nextPayDate.getDate()-14);
document.writeln("<p>Previous pay Date: " + basePayDate.toString());
document.writeln("<p>Current Date: " + today.toString());
document.writeln("<p>Next pay Date: " + nextPayDate.toString());
This won't hit odd problems, assuming the core date services work as expected. I have to admit, I didn't test it out to many years into the future...
Note: I had a similar issue; I wanted to create an array of dates on a weekly basis, ie., start date 10/23/2011 and go for 12 weeks. My code was more or less this:
var myDate = new Date(Date.parse(document.eventForm.startDate.value));
var toDate = new Date(myDate);
var week = 60 * 60 * 24 * 7 * 1000;
var milliseconds = toDate.getTime();
dateArray[0] = myDate.format('m/d/Y');
for (var count = 1; count < numberOccurrences; count++) {
milliseconds += week;
toDate.setTime(milliseconds);
dateArray[count] = toDate.format('m/d/Y');
}
Because I didn't specify the time and I live in the US, my default time was midnight, so when I crossed the daylight savings time border, I moved into the previous day. Yuck. I resolved it by setting my time of day to noon before I did my week calculation.