A bit new at this I hope someone can help me :)
I have a list of properties in Col 24 and a "room status" in Col 35 and a contract expiry date in Col 37.
I need to send email reminder to myself 30 days before expiry to send email to the person and 27 days before expiry a reminder email to myself to follow up if I have response. I have this script ready but need it to trigger only if the status is "NO RENEW" in Col 35.
Below is the script I have:
function emailAlert(){
// 27 days from now
var twoWeeksFromToday = new Date();
twoWeeksFromToday.setDate(twoWeeksFromToday.getDate() + 27);
var twoWeeksMonth = twoWeeksFromToday.getMonth() + 1;
var twoWeeksDay = twoWeeksFromToday.getDate();
var twoWeeksYear = twoWeeksFromToday.getFullYear();
// 1 month from now
var newToday = new Date()
var oneMonthFromToday = new Date(newToday.setMonth(newToday.getMonth()+1));
var oneMonthMonth = oneMonthFromToday.getMonth() + 1;
var oneMonthDay = oneMonthFromToday.getDate();
var oneMonthYear = oneMonthFromToday.getFullYear();
// getting data from spreadsheet
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("dash");
var startRow = 3; // First row of data to process
var numRows = 4; // Number of rows to process
var dataRange = sheet.getRange(startRow, 24, numRows, 41);
var data = dataRange.getValues();
//looping through all of the rows
for (var i = 0; i < data.length; ++i) {
var row = data[i];
var expireDateFormat = Utilities.formatDate(
new Date(row[13]),
'ET',
'dd/MM/yyyy'
);
//expiration date information
var expireDateMonth = new Date(row[13]).getMonth() + 1;
var expireDateDay = new Date(row[13]).getDate();
var expireDateYear = new Date(row[13]).getFullYear();
//checking for expiry date 27 days from now
Logger.log('2 weeks month, expire month' + twoWeeksMonth + expireDateMonth);
if (
expireDateMonth === twoWeeksMonth &&
expireDateDay === twoWeeksDay &&
expireDateYear === twoWeeksYear
) {
var subject =
row[11] + // Status
'\n' +
' - ' +
'\n' +
row[0] + // Address
'\n' +
' - ' +
'\n' +
'Did we get a response ? ';
MailApp.sendEmail('hello#gmail.com', subject, message);
Logger.log('2 weeks from now');
}
//checking for expiry date 1 month from now
if (
expireDateMonth === oneMonthMonth &&
expireDateDay === oneMonthDay &&
expireDateYear === oneMonthYear
) {
var subject =
row[11] + // Status
'\n' +
' - ' +
'\n' +
row[0] + // Address
'\n' +
' - ' +
'\n' +
'CONTRACT ENDING ';
MailApp.sendEmail('hello#gmail.com', subject, message);
Logger.log('1 month from now');
}
}
}
I need to convert Julian date (YYYYDDD) to Gregorian date (YYYYMMDD) in Scala.
I got this far:
import java.text.SimpleDateFormat;
val format1 = new java.text.SimpleDateFormat("yyyyddd")
println(format1.parse("2018022"))
The result is: Mon Jan 22 00:00:00 CST 2018
I need help to get output in "YYYYMMDD" format
See if this does it for you.
import java.text.SimpleDateFormat
val format1 = new SimpleDateFormat("yyyyddd")
new SimpleDateFormat("yyyyMMdd").format(format1.parse("2018022"))
//res0: String = 20180122
Or this, which demonstrates the relationships a little better.
val jDate: String = "2018022"
val gDate: String = new SimpleDateFormat("yyyyMMdd").format(
new SimpleDateFormat("yyyyddd").parse(jDate))
You can use below functions to convert the same. I'am using the same function on my website.
function julian2d($indate) {
$year = substr($indate,0,2);
$day = ltrim(substr($indate,strlen($indate)-3,3),'0'); /* Day part with leading zeroes stripped */
if ($year == 70 && $day == 1) $outdate = 1;
else if ($year == 70) $outdate = ($day-1)*24*60*60;
else if ($year >= 0 && $year <= 99 && $day > 0 && $day <= 366) {
$outdate = strtotime('01-Jan-' . $year); /* Date on Jan 1 of the year */
if ($outdate >= 0) {
$outdate = $outdate + ($day-1)*24*60*60;
} else $outdate = FALSE;
} else $outdate = FALSE;
return $outdate;
}
I'm working on an application that requires the use of getting dates for national holidays.
Below, I was able to get Memorial Day:
// Set the components for Memorial Day (last Monday of May)
let memorialDayComps = NSDateComponents()
memorialDayComps.weekday = 2
memorialDayComps.month = 5
memorialDayComps.year = currentYear
var mondaysOfMay = [NSDate]()
for var i = 1; i <= 5; i++ {
memorialDayComps.weekdayOrdinal = i
let monday = calendar.dateFromComponents(memorialDayComps)
let components = calendar.components(.CalendarUnitMonth, fromDate: monday!)
if components.month == 5 {
mondaysOfMay.append(monday!)
}
}
let memorialDayDate = mondaysOfMay.last
Because the dates are pretty well set, I am able to successfully create NSDate instances for the following holidays:
New Year's Day
Martin Luther King, Jr. Day
Presidents' Day
Memorial Day
Independence Day
Labor Day
Thanksgiving Day
Christmas Day
However, the only one that I am having difficulty figuring out how to get is Easter. It varies every year, so I'm curious as to whether anyone else has been able so successfully get the date for Easter via an API or other means.
I was able to find a gist on GitHub that has a solution that was accurate for calculating and returning an NSDate for Easter.
The code below is what the gist contains:
// Easter calculation in swift after Anonymous Gregorian algorithm
// Also known as Meeus/Jones/Butcher algorithm
func easter(Y : Int) -> NSDate {
let a = Y % 19
let b = Int(floor(Double(Y) / 100))
let c = Y % 100
let d = Int(floor(Double(b) / 4))
let e = b % 4
let f = Int(floor(Double(b+8) / 25))
let g = Int(floor(Double(b-f+1) / 3))
let h = (19*a + b - d - g + 15) % 30
let i = Int(floor(Double(c) / 4))
let k = c % 4
let L = (32 + 2*e + 2*i - h - k) % 7
let m = Int(floor(Double(a + 11*h + 22*L) / 451))
let components = NSDateComponents()
components.year = Y
components.month = Int(floor(Double(h + L - 7*m + 114) / 31))
components.day = ((h + L - 7*m + 114) % 31) + 1
components.timeZone = NSTimeZone(forSecondsFromGMT: 0)
let cal = NSCalendar(calendarIdentifier: NSGregorianCalendar)
return cal.dateFromComponents(components)
}
println(easter(2014)) // "2014-04-20 00:00:00 +0000"
That Easter algorithm works great!
Using with Swift 4.0 and pattern matching. Pattern matching made it easier for me to add other days based on month, day, weekday, weekdayOrdinal.
extension Date {
var isUSHoliday: Bool {
let components = Calendar.current.dateComponents([.year, .month, .day, .weekday, .weekdayOrdinal], from: self)
guard let year = components.year,
let month = components.month,
let day = components.day,
let weekday = components.weekday,
let weekdayOrdinal = components.weekdayOrdinal else { return false }
let easterDateComponents = Date.dateComponentsForEaster(year: year)
let easterMonth: Int = easterDateComponents?.month ?? -1
let easterDay: Int = easterDateComponents?.day ?? -1
let memorialDay = Date.dateComponentsForMemorialDay(year: year)?.day ?? -1
// weekday is Sunday==1 ... Saturday==7
// weekdayOrdinal is nth instance of weekday in month
switch (month, day, weekday, weekdayOrdinal) {
case (1, 1, _, _): return true // Happy New Years
case (1, 0, 2, 3): return true // MLK - 3rd Mon in Jan
case (2, 0, 2, 3): return true // Washington - 3rd Mon in Feb
case (easterMonth, easterDay, _, _): return true // Easter - rocket science calculation
case (5, memorialDay, _, _): return true // Memorial Day
case (7, 4, _, _): return true // Independence Day
case (9, 0, 2, 1): return true // Labor Day - 1st Mon in Sept
case (10, 0, 2, 2): return true // Columbus Day - 2nd Mon in Oct
case (11, 11, _, _): return true // Veterans Day
case (11, 0, 5, 4): return true // Happy Thanksgiving - 4th Thurs in Nov
case (12, 25, _, _): return true // Happy Holidays
case (12, 31, _, _): return true // New years Eve
default: return false
}
}
static func dateComponentsForMemorialDay(year: Int) -> DateComponents? {
guard let memorialDay = Date.memorialDay(year: year) else { return nil }
return NSCalendar.current.dateComponents([.year, .month, .day, .weekday, .weekdayOrdinal], from: memorialDay)
}
static func memorialDay(year: Int) -> Date? {
let calendar = Calendar.current
var firstMondayJune = DateComponents()
firstMondayJune.month = 6
firstMondayJune.weekdayOrdinal = 1 // 1st in month
firstMondayJune.weekday = 2 // Monday
firstMondayJune.year = year
guard let refDate = calendar.date(from: firstMondayJune) else { return nil }
var timeMachine = DateComponents()
timeMachine.weekOfMonth = -1
return calendar.date(byAdding: timeMachine, to: refDate)
}
static func easterHoliday(year: Int) -> Date? {
guard let dateComponents = Date.dateComponentsForEaster(year: year) else { return nil }
return Calendar.current.date(from: dateComponents)
}
static func dateComponentsForEaster(year: Int) -> DateComponents? {
// Easter calculation from Anonymous Gregorian algorithm
// AKA Meeus/Jones/Butcher algorithm
let a = year % 19
let b = Int(floor(Double(year) / 100))
let c = year % 100
let d = Int(floor(Double(b) / 4))
let e = b % 4
let f = Int(floor(Double(b+8) / 25))
let g = Int(floor(Double(b-f+1) / 3))
let h = (19*a + b - d - g + 15) % 30
let i = Int(floor(Double(c) / 4))
let k = c % 4
let L = (32 + 2*e + 2*i - h - k) % 7
let m = Int(floor(Double(a + 11*h + 22*L) / 451))
var dateComponents = DateComponents()
dateComponents.month = Int(floor(Double(h + L - 7*m + 114) / 31))
dateComponents.day = ((h + L - 7*m + 114) % 31) + 1
dateComponents.year = year
guard let easter = Calendar.current.date(from: dateComponents) else { return nil } // Convert to calculate weekday, weekdayOrdinal
return Calendar.current.dateComponents([.year, .month, .day, .weekday, .weekdayOrdinal], from: easter)
}
}
Here is a Swift 5 implementation of O'Beirne's algorithm with inline documentation.
The code is more compact than the implementations in the other provided answers because it makes use of Integer arithmetic and thus removes the need to explicitly round numbers and convert between Floats and Ints.
/// **How ten divisions lead to Easter** *by T. H. O'Beirne, New Scientist, march 30 1961 - Vol. 9,Nr. 228*
func easter(in year: Int) -> (day: Int, month: Int) {
/// Identify the position of the `year` in a 19-year cycle, to use this later to determine the principal constituent of the changes of full-moon dates from year to year
let a = year % 19
/// Take note of the corrections which the Gregorian calendar introduces in century years
let (b, c) = year.quotientAndRemainder(dividingBy: 100)
/// Take account of the leap-year exceptions in century years
let (d, e) = b.quotientAndRemainder(dividingBy: 4)
/// Provide similarly for the century years auxiliary corrections to the new-moon and full-moon dates
let g = (8*b + 13) / 25
/// Determine the number of days between 21 March and the coincident or next full moon, if no special exceptions arise
let h = (19*a + b - d - g + 15) % 30
/// Determine the position of the year in the ordinary leap-year cycle of four years
let (i, k) = c.quotientAndRemainder(dividingBy: 4)
/// Determine number of days (between 0 and 6) until the Sunday *after* full moon
let l = (2*e + 2*i - h - k + 32) % 7
/// The exceptions which make a 29-day month interrupt the regularity of a simpler pattern need here be considered *only* when they transfer the full moon *from a Sunday to a Saturday*: the *Easter date* is unaffected in other cases. When appropriate — 1954 and 1981 are quite rare examples — we have m=1; otherwise m=0 : this permits the necessary correction (failing which the Easter date *would* be 26 April in 1981.
let m = (a + 11*h + 19*l) / 433
/// Determine days between March 22 and Easter
let relativeDayCount = h + l - 7*m
/// Convert relative day count into absolute month and day index
let month = (relativeDayCount + 90) / 25
return (day: (relativeDayCount + 33*month + 19) % 32, month)
}
func easterDate(in year: Int) -> Date {
let (day, month) = easter(in: year)
let components = DateComponents(
timeZone: TimeZone(secondsFromGMT: 0),
year: year, month: month, day: day
)
return Calendar(identifier: .gregorian).date(from: components)!
}
Swift 4:
func easter(Y : Int) -> Date {
let a = Y % 19
let b = Int(floor(Double(Y) / 100))
let c = Y % 100
let d = Int(floor(Double(b) / 4))
let e = b % 4
let f = Int(floor(Double(b+8) / 25))
let g = Int(floor(Double(b-f+1) / 3))
let h = (19*a + b - d - g + 15) % 30
let i = Int(floor(Double(c) / 4))
let k = c % 4
let L = (32 + 2*e + 2*i - h - k) % 7
let m = Int(floor(Double(a + 11*h + 22*L) / 451))
var components = DateComponents()
components.year = Y
components.month = Int(floor(Double(h + L - 7*m + 114) / 31))
components.day = ((h + L - 7*m + 114) % 31) + 1
components.timeZone = TimeZone(secondsFromGMT: 0)
return Calendar.autoupdatingCurrent.date(from: components)!
}
print(easter(Y: 2018)) // "2018-04-01 00:00:00 +0000"
OBJECTIVE-C!
-(void) easterMonthAndDayForYear: (NSInteger) Y {
NSInteger a = Y % 19;
NSInteger b = (int) (floor( ((double)Y) / 100.0));
NSInteger c = Y % 100;
NSInteger d = (int)(floor(((double)b) / 4.0));
NSInteger e = b % 4;
NSInteger f = (int)(floor(((double)(b+8)) / 25.0));
NSInteger g = (int)(floor(((double)(b-f+1)) / 3.0));
NSInteger h = (19*a + b - d - g + 15) % 30;
NSInteger i = (int)(floor(((double)c) / 4.0));
NSInteger k = c % 4;
NSInteger L = (32 + 2*e + 2*i - h - k) % 7;
NSInteger m = (int)(floor(((double)(a + 11*h + 22*L)) / 451.0));
NSDateComponents *components = [[NSCalendar currentCalendar] components:NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear |NSCalendarUnitTimeZone fromDate:[NSDate date]];
components.year = Y;
components.month = (int)(floor((double)(h + L - 7*m + 114) / 31.0));
components.day = ((h + L - 7*m + 114) % 31) + 1;
components.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0];
self.easterDayCache[#(Y)] = #{#"month": #(components.month), #"day":#(components.day)
};
I have a Google Sheet with three columns:
- Date and time (timestamp)
- Duration
- Description
I have an script that when I write something in 'Description', inserts in 'Date' the date and time at this moment, and the 'Duration':
function onEdit(e) {
if(e.source.getActiveSheet().getName() == "Sheet2" ) {
var col = e.source.getActiveCell().getColumn();
if(col == 3 ) {
// I'm in column three
var cellTimeStamp = e.range.offset(0,-2); // First column of the same row
var cellTimeDiff = e.range.offset(0,-1); // Second column of the same row
var cellTimePrev = e.range.offset(-1,-2); // First column of the previous row
var timeTimeStamp = new Date();
var iniTime = cellTimePrev.getValue().getTime();
var finTime = timeTimeStamp.getTime() ;
var timeDiff = String(finTime - iniTime) ;
cellTimeStamp.setValue(timeTimeStamp);
cellTimeDiff.setValue(timeDiff); // [***]
}
}
}
When this executes (as an event) in the column of 'Duration' there is NOT something in the format of 'HH:mm:ss'.
But if I remove the last line in this script and adds this formulae in the sheet:
=A3-A2 (in row 3)
=A4-A3 (in row 4)
...
then it works ok.
I'd like to know how to meet the same result but with a script.
Thanks in advance.
timeDiff is the result of finTime - iniTime which are both native date object values, which means we have milliseconds .
converting that in hh:mm:ss is simple math... : 60 seconds in a minute and 60 minutes in an hour...
A simple code could be like this :
function msToTime(s) {
var ms = s % 1000;
s = (s - ms) / 1000;
var secs = s % 60;
s = (s - secs) / 60;
var mins = s % 60;
var hrs = (s - mins) / 60;
return hrs + ':' + mins + ':' + secs; // milliSecs are not shown but you can use ms if needed
}
If you prefer formating your string more conventionally (2 digits for each value) don't forget you can use Utilities.formatString() to do so.
example below :
return Utilities.formatString("%02d",hrs) + ':' + Utilities.formatString("%02d",mins) + ':' + Utilities.formatString("%02d",secs);
EDIT
Following your comment :
Spreadsheets are smarter than you think, you can try the code below and you will see that the result is actually a time value.(check by double clicking on it)
function test() {
var sh = SpreadsheetApp.getActiveSheet();
var t1 = sh.getRange('a1').getValue().getTime();
var t2 = sh.getRange('b1').getValue().getTime();
sh.getRange('c1').setValue(msToTime(t1-t2)).setNumberFormat('hh:mm:ss');
}
function msToTime(s) {
var ms = s % 1000;
s = (s - ms) / 1000;
var secs = s % 60;
s = (s - secs) / 60;
var mins = s % 60;
var hrs = (s - mins) / 60;
return hrs + ':' + mins + ':' + secs; // milliSecs are not shown but you can use ms if needed
}
note that setNumberFormat('hh:mm:ss') is optional, it's only there to force the spreadsheet to display hour:min:sec format but automatic mode works as well.
I am trying to calculate the time difference between 2 date time strings.
I have 2 inputs where the input string is something like this "1:00 PM" and the second one "3:15 PM". I want to know the time difference. So for the above example I want to display 3.15
What I have done:
Converted the time to a 24 hours format. So "1:00 PM" becomes "13:00:00"
Appended the new time to a date like so: new Date("1970-1-1 13:00:00")
Calculated the difference like so:
Code:
var total = Math.round(((new Date("1970-1-1 " + end_time) -
new Date("1970-1-1 " + start_time) ) / 1000 / 3600) , 2 )
But the total is always returning integers and not decimals, so the difference between "1:00 PM" and "3:15 PM" is 2 not 2.15.
I have also tried this (using jQuery, but that is irrelevant):
$('#to_ad,#from_ad').change(function(){
$('#total_ad').val( getDiffTime() );
});
function fixTimeString(time){
var hours = Number(time.match(/^(\d+)/)[1]);
var minutes = Number(time.match(/:(\d+)/)[1]);
var AMPM = time.match(/\s(.*)$/)[1];
if(AMPM == "PM" && hours<12) hours = hours+12;
if(AMPM == "AM" && hours==12) hours = hours-12;
var sHours = hours.toString();
var sMinutes = minutes.toString();
if(hours<10) sHours = "0" + sHours;
if(minutes<10) sMinutes = "0" + sMinutes;
return sHours + ':' + sMinutes + ':00';
}
function getDiffTime(){
var start_time = fixTimeString($('#from_ad').val());
var end_time = fixTimeString($('#to_ad').val());
var start = new Date("1970-1-1 " + end_time).getTime(),
end = new Date("1970-1-1 " + start_time).getTime();
return parseInt(((start - end) / 1000 / 3600, 10)*100) / 100;
}
But the total_ad input is displaying only integer values.
How can I fix this problem?
Math.round rounds to the nearest integer, multiply and divide instead
var start = new Date("1970-1-1 " + start_time).getTime(),
end = new Date("1970-1-1 " + end_time).getTime();
var total = (parseInt(((start-end) / 1000 / 3600)*100, 10)) / 100;
FIDDLE
When you take the time 15:15:00 and subtract 13:00:00, you're left with 2.15 hours, not 3.15, and this example would return 2.15 even without making sure there is only two decimals, but for other times that might not be the case.
You could also use toFixed(2), but that would leave you with 3.00 and not 3 etc.
This is how I calculate it:
calculateDiff();
function calculateDiff(){
_start = "7:00 AM";
_end = "1:00 PM";
_start_time = parseAMDate(_start);
_end_time = parseAMDate(_end);
if (_end_time < _start_time){
_end_time = parseAMDate(_end,1);
}
var difference= _end_time - _start_time;
var hours = Math.floor(difference / 36e5),
minutes = Math.floor(difference % 36e5 / 60000);
if (parseInt(hours) >= 0 ){
if (minutes == 0){
minutes = "00";
}
alert(hours+":"+minutes);
}
}
function parseAMDate(input, next_day) {
var dateReg = /(\d{1,2}):(\d{2})\s*(AM|PM)/;
var hour, minute, result = dateReg.exec(input);
if (result) {
hour = +result[1];
minute = +result[2];
if (result[3] === 'PM' && hour !== 12) {
hour += 12;
}
}
if (!next_day) {
return new Date(1970, 01, 01, hour, minute).getTime();
}else{
return new Date(1970, 01, 02, hour, minute).getTime();
}
}