Apologies in advance for my (something less than) basic knowledge of java script.
Can someone explain in basic – but specific – terms how this script is calculating?
Here is the script:
var d = new Date(year, month, day);
var e = new Date(d.getTime() + offset * 24 * 60 * 60 * 1000);
var month_out = e.getUTCMonth();
var day_out = e.getDate();
var year_out = e.getUTCFullYear();
date_out = month_out + "-" + day_out + "-" + year_out;
year = 2013
month = 12
day = 01
offset = 15
The offset is the “payment terms” and the date is the invoice date. The output is supposed to be the invoice date plus the offset to arrive at “12-16-2013”
That is NOT what it is kicking out and I need to figure out how to fix it.
One customer is having dates show up as: 0-16-2014
I don’t know which string is wrong or how it should read in its place. This is one piece of an entire function that pulls an invoice date from an XML file, strips the time from the date and creates a new "Date_Due" using the offset. This script is the only area that is failing.
Can anyone help?
getUTCMonth() returns 0 based months - 0 is January, 1 is February, etc.
Add 1 to this value to make it more human readable.
See docs for more info.
Related
I created a Google Form to collect user input, including the expiration date of a contract.
I need to create a reminder date (6 months before the expiration date) in a new column of the gsheets that is linked to the form. Using the Event Object namedValues, I extracted the expiration date from gsheet. I converted the date to milliseconds and subtracted the number of milliseconds equal to 6 months (or thereabouts). However, the output that got sent back to the googlesheet is an undefined number.
I must be misunderstanding something and was hoping someone more skilled in this can help me out. Is the data type wrong? Thanks for any illumination you can provide.
function onFormSubmit(e) {
var responses = e.namedValues;
var MILLIS_PER_DAY = 1000 * 60 * 60 * 24;
var expireDate = responses['Expiration Date'][0].trim();
var expireDate_ms = expireDate * 1000; // converting to milliseconds
var noticeDate = expireDate_ms - (183 * MILLIS_PER_DAY);
// Create a new column to store the date to send out notice of expiration or renewal
var sheet = SpreadsheetApp.getActiveSheet();
var row = sheet.getActiveRange().getRow();
var column = e.values.length + 1;
sheet.getRange(row, column).setValue(noticeDate);
}
I’d recommend you to use a formula instead:
={"Reminder"; ARRAYFORMULA(IF(NOT(ISBLANK(B2:B)); EDATE(B2:B; -6); ""))}
Add this to the header of an empty column, it will generate all data in that column for you. Change B for the column you have the expiration date on.
If you really need to use Google Apps Script you can, but JavaScript is notorious for having bad date support (at least without an external library). To do it, you’ll have to manually parse the string, modify the date and format it back to the date number:
const dateParts = e.namedValues['Expiration Date'][0].trim().split('/')
const date = new Date(
Number(dateParts[2]), // Year
Number(dateParts[1]) - 1 - 6, // Month. -1 because January is 0 and -6 for the 6 months before
Number(dateParts[0]) // Day
)
const numericDate = Math.floor((date.getTime() - new Date(1900, 0, 1).getTime()) / (1000 * 60 * 60 * 24))
This example only works if the format used in the sheet is DD/MM/YYYY.
The numeral value of date is the number of days since the first day of 1900 (link to documentation). So we need to subtract it and change it from milliseconds to days. Math.floor ensures that it’s not decimal.
You can set numericDate to the cell but make sure the numeric format is Date.
References
EDATE - Docs Editors Help
ARRAYFORMULA - Docs Editors Help
Date - JavaScript (MDN)
DATE - Docs Editor Help
Marti's answer was helpful but the math didn't quite work out because the suggested solution was to minus 6 from the month retrieved. But the reminder date is supposed to be 6 months from the date (taking into account the year and the date), so it doesn't quite work.
The solution I worked out is the following:
function onFormSubmit(e) {
const expireDateParts = e.namedValues['Expiration Date'][0].trim();
if (expireDateParts != ""){
expireDateParts.split('/');
var MILLIS_PER_DAY = 1000 * 60 * 60 * 24;
const expireDate = new Date(
Number(expireDateParts[2]), // Year
Number(expireDateParts[0]) - 1, // Month. -1 because January is '0'
Number(expireDateParts[1]) // Day
);
const reminderNumericDate = Math.floor((expireDate.getTime() - 183 * MILLIS_PER_DAY));
var reminderDate = formatDate(reminderNumericDate);
// Create a new column to store the date to send out notice of expiration or renewal
var sheet = SpreadsheetApp.getActiveSheet();
var row = sheet.getActiveRange().getRow();
var column = 14 // hard-coded to Column 0;
sheet.getRange(row, column).setValue(reminderDate);
// Set up Schedule Send Mail
createScheduleSendTrigger(reminderNumericDate);
var status = 'Scheduled';
sheet.getRange(row, column+1).setValue(status);
}
}
I try to make my timepickers behave like the ones in google calendar. What I try to achieve is that if I set the start time from 10:00 to 11:00, the 2nd should follow from 11:00 to 12:00. If I set the 2nd picker from 11 to 13, the difference is now 2 hours and if I adjust the first one, the 2nd should move +2 or -2 hours depending if its earlier or later on the day.
My current jquery code is now
var d = new Date();
var start_time = $('#calendarentryform-start_time').val();
var end_time = $('#calendarentryform-end_time').val();
var diff = ( new Date('1970-01-01 ' + end_time) - new Date('1970-01-
01 ' + start_time) ) / 1000 / 60 / 60;
var new_end_time = start_time + diff;
$('#calendarentryform-start_time').on('change',function() {
$('#calendarentryform-end_time').val(new_end_time);
}
);
It manage to find for example the hour difference on 1 hour, like the calculation is correct. But when I try to add that hour for new_end_time it just post 12:001 instead of 13:00 or whatever the time is supposed to be set to. I also want it to be able to find 1,5 hours, 2,5 hours etc.
I just dont seem to get it right.
This is my first time posting a question on here however I am a long term user of StackOverflow.
I am very new to Javascript and am currently trying to solve a few issues I am having on a website I am creating for my university course.
I am trying to make a little information box on the website's dashboard that simply tells you when your next rubbish bin collection day is. This is currently every 2 weeks on a Friday, the next being 1st April. I was wondering if there was a simple way for me to display the next bin collection date until it's the day of the bin collection, where the text would change to say 'bin collection today!' and after about 6pm it would change to the next collection date in a fortnight.
Sorry if this is extremely poorly worded! The website will only be used in the UK so I don't need to worry about time zones.
Any help would be very much appreciated!
Many thanks,
Emily
Below is some code to show how it might be done, hopefully there are sufficient comments.
As far as I know, some parts of the UK observe daylight saving but the following should not be affected by any change of timezone since it uses local date methods.
Any date can be used for the start of the cycle, I've chosen 10 June 2011 totally randomly. Also, any time of day can be used to change the message on the final day from "put your bins out today" to the standard "next cycle is in x days".
The algorithm is calculate the number of milliseconds to the next full fortnight from the start date by subtracting the number of milliseconds from the last full fortnight from the milliseconds per fortnight. Then the remainder is converted to full days.
To save ambiguity on the day before the cycle ends (in this case, a Thursday) the message says the cycle ends "tomorrow" rather than in 1 day, and on the day itself, up to 18:00 or 6 pm it says the cycle ends today. After that, it says the cycle ends in 14 days or less.
// Date objects are based on milliseconds (8.64e7 per day)
// Calculate milliseconds for a fortnight
var msPerFortnight = 8.64e7 * 14;
// Any date can be the start of the fortnightly cycle
// Make Friday 10 June 2011 first day of cycle,
// Cycles end on 25 March, 6 April 2016.
// Note months are zero based so June is 5
var firstDayOfCycle = new Date(2011, 5, 10);
// Time of day to stop showing "put bins out today" message on start/end day
// 18 is 6 pm
var endHour = 18;
// Get the day name for the cycle start/end
var dayName = ['Sunday','Monday','Tuesday','Wednesday','Thursday',
'Friday','Saturday'][firstDayOfCycle.getDay()];
// Convert end hour to convenient format with am/pm
var endHourNeat = (endHour % 12 || 12) + ' ' + (endHour < 12? 'am' : 'pm');
// Get a date for now
var now = new Date();
// Get milliseconds to next full fortnight by
// msPerFortnight minus milliseconds since last full fortnight
var m = msPerFortnight - ((new Date() - firstDayOfCycle) % msPerFortnight);
// Calculate time remaining full days
var daysLeft = Math.ceil(m / 8.64e7);
// Create a human friendly message
var message;
// If more then one day left, or after 18:00 on last day, show this message
if (daysLeft == 14 && now.getHours() < endHour) {
message = 'Today is ' + dayName + ', so please put your bins out before ' + endHourNeat + '!';
} else if (daysLeft > 1 ) {
message = 'Put your bins out on ' + dayName + ' in ' + daysLeft +
' day' + (daysLeft == 1?'':'s') + ' time.';
} else if (daysLeft == 1) {
message = 'Put your bins out tomorrow, on ' + dayName + '.';
}
document.write(message);
You can even add the date of the end of the cycle and add ordinal, so it might read "Put your bins out on Friday the 25th, in 3 days time". But I'll leave that up to you.
A possible solution is to use Unix epoch, because they give you your time in seconds from 1/1/1970. By using this we can find how far we are into a fortnight. I found that Math.floor(Date.parse("2016-04-01")/86400000)%14equals 8.
Then your code might be:
var days_into_fortnight=Math.floor(Date.now()/86400000)%14;
var string_to_show;
var days_to_collection;
if (days_into_fortnight==8){
string_to_show="Bin collection!";
}
else{
if(days_into_fortnight<8){
days_to_collection=8-days_into_fortnight;
}
else{
days_to_collection=22-days_into_fortnight;
}
string_to_show=days_to_collection.toString()+" day(s) to collection!";
}
Edit:spelling
I need to know the date for last Sunday for given date in php & javascript
Let's have a function give_me_last_Sunday
give_me_last_Sunday('20110517') is 20110515
give_me_last_Sunday('20110604') is 20110529
The full backup is done on Sundays = weekly. If I want to restore daily backup I need full (weekly) and daily backup. I need to copy backup files before restoring to temp directory so I restoring daily backup I need to know what weekly backup file I need to copy along the daily file.
My thought was to get Julian representation (or something similar) for the given date and then subtract 1 and check if it is Sunday ... Not sure if this is the best idea and how to convert given date into something I can subtract.
Based on Thomas' effort, and provided the input string is exactly the format you specified, then:
function lastSunday(d) {
var d = d.replace(/(^\d{4})(\d{2})(\d{2}$)/,'$1/$2/$3');
d = new Date(d);
d.setDate(d.getDate() - d.getDay());
return d;
}
Edit
If I were to write that now, I'd not depend on the Date object parsing the string but do it myself:
function lastSunday(s) {
var d = new Date(s.substring(0,4), s.substring(4,6) - 1, s.substring(6));
d.setDate(d.getDate() - d.getDay());
return d;
}
While the format yyyy/mm/dd is parsed correctly by all browsers I've tested, I think it's more robust to stick to basic methods. Particularly when they are likely more efficient.
Ok so this is for JavaScript only. You have an input that you need to extract the month, date, and year from. The following is just partly an answer then on how to get the date:
<script type="text/javascript">
var myDate=new Date();
myDate.setFullYear(2011,4,16)
var a = myDate.getDate();
var t = myDate.getDay();
var r = a - t;
document.write("The date last Sunday was " + r);
</script>
So the setFullYear function sets the myDate to the date specified where the first four digits is the year, the next are is the month (0= Jan, 1= Feb.,...). The last one is the actually date. Then the above code gives you the date of the Sunday before that. I am guessing that you can add more code to get the month (use getMonth() method). Here are a few links that might be helpful
http://www.w3schools.com/js/js_obj_date.asp
http://www.w3schools.com/jsref/jsref_setFullYear.asp
http://www.w3schools.com/jsref/jsref_getMonth.asp
(You can probably find the other functions that you need)
I hope this helps a bit even though it is not a complete answer.
Yup and strtotime has been ported to JS for eg http://phpjs.org/functions/strtotime:554 here.
final code (big thanks to #Thomas & #Rob)
function lastSunday(d) {
var d = d.replace(/(^\d{4})(\d{2})(\d{2}$)/,'$1/$2/$3');
d = new Date(d);
d.setDate(d.getDate() - d.getDay());
year = d.getFullYear()+'';
month = d.getMonth()+1+'';
day = d.getDate()+'';
if ( month.length == 1 ) month = "0" + month; // Add leading zeros to month and date if required
if ( day.length == 1 ) day = "0" + day;
return year+month+day;
}
I have a JSON feed that drupal spits out time in this format: 2010-12-16T04:41:35Z
How do I go about formating it to X minutes/hours ago?
Take a look at the timeago jQuery plugin which can be used programtically like
var t = jQuery.timeago("2010-12-16T04:41:35Z");
or on HTML elements like
<time class="timeago" datetime="2008-07-17T09:24:17Z">July 17, 2008</time>
<script type="javascript">
jQuery(document).ready(function() {
jQuery("time.timeago").timeago();
});
</script>
I think something on this page will help you. There's a couple formatting jQuery plugins toward the bottom. Good luck!
Here is a highly relevant Stack Overflow post: How can I convert string to datetime with format specification in JavaScript?
You can use regexp object in JS to build your own regular expression, separate hours-minutes-secs from the original string and then do whatever you want.
Tip: actual_date - your original string time
does the 04:41:35 part is correct? or do you need like to take into consideration time zones and stuff?
because basically this can work:
var str = "2010-12-16T04:41:35Z"
var arr = str.split("T")
arr[0] = arr[0].split("-")
arr[1] = (arr[1].replace(/Z/ig,"")).split(":")
var year = arr[0][0]
var month = parseInt(arr[0][1],10)-1
var day = arr[0][2]
var hours = arr[1][0]
var minutes = arr[1][1]
var seconds = arr[1][2]
var d = new Date(year, month, day, hours, minutes, seconds, 0);
var now = (new Date())
var diffMS = now.getTime() - d.getTime()
//alert ("difference in milliseconds: " + diffMS)
var hoursago = diffMS/1000/60
var ANDminutes = (diffMS - Math.floor(hoursago) * 1000*60)/1000
alert (Math.floor(hoursago) + " hours and " + ANDminutes + " minutes ago")
<shameless_plug>
Here's a library which give you a humanized time difference.
https://github.com/layam/js_humanized_time_span
The output is completely customizable, allowing you to set different output formats for various time bands; So you could have:
'10 seconds ago'
or
'3 days and 2 hours ago'
you can even set custom time units.
Additionally it's native JS and so doesn't rely on any framework.
</shameless_plug>