Related
I want to make a list of last months dates in cell A5:A35.
I am currently just using formulas but it is going to list all the days regardless of count in the month. So when I make the sheet for November, it's going to have December 1st on the list. I don't want that.
I tried scripting to get the current month and searching the range for that month but it's not working and seems convoluted. There must be a cleaner way.
I just want to programmatically list the days in the prior month.
I have this
Code function won't work on mobile
function assignDates() {
const cell = sheet.getRange('A5:A35');
cell.setFormula(=EOMONTH(TODAY(),-2)+D5
d5 is a hidden column with 1,2,3... etc. It's a really cheap way to do it.
It will list 31 days regardless of the length of the month.
Now to deal with this, I tried to make a script to get the current month and then delete entries that contain that but it does not work.
//check to see if dates fall within month
function dateCheck(sheet){
var sheet = SpreadsheetApp.getActive().getSheetByName('test');
//get current month
var month = Utilities.formatDate(new Date(), "GMT-5", "MMMM")
// Delete days that fall out of range
var dayRange = sheet.getRange('A5:A36').getDisplayValues();
dayRange.forEach((date) => { if (date.toString().includes(month))
{ sheet.getRangeList(dayRange).clearContent() } })
}
=SEQUENCE(DAYS(EOMONTH(TODAY(),)+1,EOMONTH(TODAY(),-1)+1),1,EOMONTH(TODAY(),-1)+1)
DAYS to calculate number of days in this month
EOMONTH to get end date of last month and this month
SEQUENCE to create sequence of dates.
You need to change TODAY() to a static date string, if you don't want the sequence to change every month.
Get Last Month and This Month Calendar on a Spreadsheet
Code:
function getCalendar() {
const ss = SpreadsheetApp.getActive()
const sh = ss.getActiveSheet();
sh.clear();
let oA = [];
oA.push(monthlyCalendar(new Date().getMonth() - 1, null, true));//helper function
oA.push(monthlyCalendar(new Date().getMonth(), null, true));//helper function
//oA.push(monthlyCalendar(new Date().getMonth() + 1, null, true));
oA.forEach((obj, i) => {
if (i == 0) {
sh.getRange(1, 1, 2, obj.cA[0].length).setFontWeight('bold');
sh.getRange(1, 1, obj.cA.length, obj.cA[0].length).setValues(obj.cA);
} else {
let sr = sh.getLastRow() + 2;
sh.getRange(sr, 1, 2, obj.cA[0].length).setFontWeight('bold');
sh.getRange(sr, 1, obj.cA.length, obj.cA[0].length).setValues(obj.cA);
if (obj.roff && obj.coff) {
sh.getRange(sr, 1).offset(obj.roff, obj.coff).setFontWeight('bold').setFontColor('red');//sets the current date to bold and red
}
}
});
}
Helper Function:
function monthlyCalendar(m, wsd, ret) {
var m = m || new Date().getMonth();
var wsd = wsd || 1;//defaults to Monday
var ret = ret || false;
const td = new Date();
const [cy,cm,cd] = [td.getFullYear(),td.getMonth(),td.getDate()];
const dA = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
const oA = [...Array.from(Array(7).keys(), idx => dA[(idx + wsd) % 7])]
let dObj = {};
let midx = {};
let rObj = {cA:null,roff:null,coff:null};
oA.forEach(function (e, i) { dObj[e] = i; });
const mA = [...Array.from(new Array(12).keys(), x => Utilities.formatDate(new Date(2021, x, 15), Session.getScriptTimeZone(), "MMM"))];
mA.forEach((e, i) => { midx[i] = i; })
let cA = [];
let bA = [];
let wA = [null, null, null, null, null, null, null];
const ss = SpreadsheetApp.getActive();
const sh = ss.getActiveSheet();
sh.clear();
const year = new Date().getFullYear();
let i = midx[m % 12];
let month = new Date(year, i, 1).getMonth();
let dates = new Date(year, i + 1, 0).getDate();
cA.push([mA[month], dates, '', '', '', '', '']);
bA.push(['#ffffff', '#ffffff', '#ffffff', '#ffffff', '#ffffff', '#ffffff', '#ffffff']);
cA.push(oA)
//bA.push(['#ffff00', '#ffff00', '#ffff00', '#ffff00', '#ffff00', '#ffff00', '#ffff00']);
let d = [];
let ddd = [];
for (let j = 0; j < dates; j++) {
let day = new Date(year, i, j + 1).getDay();
let date = new Date(year, i, j + 1).getDate();
if (day < wA.length) {
wA[dObj[dA[day]]] = date;
}
if(cy == year && cm == month && cd == date) {
rObj.roff = cA.length;
rObj.coff = dObj[dA[day]];
}
if (dA[day] == oA[wA.length - 1] || date == dates) {
cA.push(wA);
//bA.push(['#ffffff', '#ffffff', '#ffffff', '#ffffff', '#ffffff', '#ffffff', '#ffffff']);
wA = ['', '', '', '', '', '', ''];
}
}
if (!ret) {
rObj.cA = cA;
sh.getRange(1, 1, rObj.cA.length, rObj.cA[0].length).setValues(cA);
if (rObj.roff && rObj.coff) {
sh.getRange(1, 1).offset(rObj.roff, rObj.coff).setFontWeight('bold').setFontColor('red');
}
} else {
rObj.cA = cA;
return rObj;
}
}
Demo:
Nice challenge!
Enter the following function on A5:
=arrayformula(if(eomonth(today(),-2)+row(A5:A35)+1-row()>eomonth(today(),-1),"",eomonth(today(),-2)+row(A5:A35)+1-row()))
It will retrieve all dates from the 1st until the last date of the last month (related to today()). until 31th, 30th, 28th, or 29th dynamically!
Cheers!
If you need a script here you go:
function myFunction() {
var today = new Date();
var year = today.getFullYear();
var month = today.getMonth(); // 0 -> January, 1 -> February, etc...
// get the number of days of the previous month
// 'zero day' of a month is the last day of a previous month
var len = new Date(year, month, 0).getDate();
// make an array with dates (strings, actually)
var options = { year: 'numeric', month: 'numeric', day: 'numeric' };
var dates = new Array(len).fill('').map((_, day) =>
[new Date(year, month-1, day+1).toLocaleString('en-US', options)])
// put the array on the sheet
SpreadsheetApp.getActiveSheet().getRange(5,1,len,1).setValues(dates);
}
Dates is a tricky thing always.
I have a DatePicker on my app and the user can't select a past date, because I'm creating a notification out of it
How can I implement a minimumDate equivalent in SwiftUI?
I tried creating an alert on my save button using “if date < Date(), else show alert”, but it didn't work.
You can provide a range to DatePicker:
#State private var date = Date()
let dateRange: ClosedRange<Date> = {
let calendar = Calendar.current
let startComponents = DateComponents(year: 2021, month: 1, day: 1)
let endComponents = DateComponents(year: 2021, month: 12, day: 31, hour: 23, minute: 59, second: 59)
return calendar.date(from:startComponents)!
...
calendar.date(from:endComponents)!
}()
var body: some View {
DatePicker(
"Start Date",
selection: $date,
in: dateRange,
displayedComponents: [.date, .hourAndMinute]
)
}
Source: https://developer.apple.com/documentation/swiftui/datepicker
I'm new to protractor and I'm verifying that the default values in some drop downs are the current date: month, day and year
This is my code which I wrote:
this.startDateMonthDropdown = element(by.xpath("//op-dropdown[#change.bind='changeStartMonth']"));
this.startDayInput = element(by.xpath("//input[#value.two-way='startDay']"));
this.startYearDropdown = element(by.xpath("//op-dropdown[#change.bind='changeStartYear']"));
function checkStartDateIsCurrentDate() {
let date = new Date(new Date().getTime() + 24 * 60 * 60 * 1000);
let currentMonth = date.getMonth() + 1;
let currentDay = date.getDate() - 1;
let currentYear = date.getFullYear();
this.startDateMonthDropdown.getText().then(function (month) {
expect(month).toEqual(currentMonth)
});
this.startDayInput.getAttribute('value').then(function (day) {
expect(day).toEqual(currentDay)
});
this.startYearDropdown.getText().then(function (year) {
expect(year).toEqual(currentYear)
});
}
When I run the test, it fails:
Expected 'July' to equal 7.
Expected '4' to equal 4.
Expected '2019' to equal 2019.
The getText() method returns a promise that will be resolved with the element's visible text (string). So you have to convert currentDay and currentYear to the string.
function checkStartDateIsCurrentDate() {
const date = new Date(new Date().getTime() + 24 * 60 * 60 * 1000);
const currentMonth = date.toLocaleString('en-us', { month: 'long' });
const currentDay = date.getDate() - 1;
const currentYear = date.getFullYear();
this.startDateMonthDropdown.getText().then(function (month) {
expect(month).toBe(currentMonth)
});
this.startDayInput.getAttribute('value').then(function (day) {
expect(day).toBe(`${currentDay}`)
});
this.startYearDropdown.getText().then(function (year) {
expect(year).toBe(`${currentYear}`)
});
}
Expected '4' to equal 4.
Expected '2019' to equal 2019.
When you interact with an element and write getText(). It takes values as text but if you want to compare with number then you must convert text to number and then verify that.
thank you for the answers. I managed to fix it and also solved the issue with the month.
This is my final code
function checkStartDateIsCurrentDate() {
let date = new Date(new Date().getTime() + 24 * 60 * 60 * 1000);
let currentMonth = date.getMonth();
let months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
let currentDay = date.getDate() - 1;
let currentYear = date.getFullYear();
this.startDateMonthDropdown.getText().then(function (month) {
expect(month).toEqual(months[currentMonth])
});
this.startDayInput.getAttribute('value').then(function (day) {
day = parseInt(day);
expect(day).toEqual(currentDay)
});
this.startYearDropdown.getText().then(function (year) {
year = parseInt(year);
expect(year).toEqual(currentYear)
});
}
I'm working on local notification scheduling module for iOS 10 which repeats local notification for example every Sunday or every Monday..etc. Lets say i scheduled a notification for this date which is 2016-12-27 10:53:22 +0000 and using UNCalendarNotificationTrigger with repeat value equals true, the notification get triggered for ones in that date, and it doesn't repeat next week at the same time.
What could be the reason for that? and how is it possible to repeat every week for specific day in iOS 10.
Here is the code for creating local notification:
let content = UNMutableNotificationContent()
content.title = object.title
content.body = object.body
content.sound = UNNotificationSound.default()
let date = object.fireDate
let triggerDate = Calendar.current.dateComponents([.year,.month,.day,.hour,.minute,.second,], from: date as Date)
let trigger = UNCalendarNotificationTrigger(dateMatching: triggerDate,
repeats: true)
// Swift
let identifier = object.id
let request = UNNotificationRequest(identifier: identifier,
content: content, trigger: trigger)
localNotification.add(request, withCompletionHandler: { (error) in
if error != nil {
// Something went wrong
print(error!)
}else {
print("Reminder \(object.id) has been added successfully at \(object.fireDate)")
}
})
Update:
I have also discovered after the notification get fired at that date and to check that there is no more pending notification exist or to check if it has been rescheduled again or not. actually with repeat equals true, it has not been scheduled again for next week.
UNUserNotificationCenter.current().getPendingNotificationRequests(completionHandler: { (notficiations) in
for localNotification in notficiations {
print(localNotification)
}
})
And the result was:
<UNNotificationRequest: 0x174223ca0; identifier: A1, content: <UNNotificationContent: 0x1742e2980; title: My Title, subtitle: (null), body: My Body, categoryIdentifier: , launchImageName: , peopleIdentifiers: (
), threadIdentifier: , attachments: (
), badge: (null), sound: <UNNotificationSound: 0x1740b1820>, hasDefaultAction: YES, shouldAddToNotificationsList: YES, shouldAlwaysAlertWhileAppIsForeground: NO, shouldLockDevice: NO, shouldPauseMedia: NO, isSnoozeable: NO, fromSnooze: NO, darwinNotificationName: (null), darwinSnoozedNotificationName: (null), trigger: <UNCalendarNotificationTrigger: 0x174223cc0; dateComponents: <NSDateComponents: 0x17415e140>
Calendar Year: 2016
Month: 12
Day: 27
Hour: 14
Minute: 46
Second: 15, repeats: YES>>
I don't know if its actually a bug in iOS or not.
Triggering date format is not proper to repeat notification in a day of a week.
Your current trigger date components includes year,month,day, etc so this notification repeat in each year in that particular month and day.Change trigger date like mentioned below to repeat notification in a day of a week.
let triggerDate = Calendar.current.dateComponents([.weekday,.hour,.minute], from: date as Date)
Here is approach which should work:
func addNotificationForAlarm(alarm: MyAlarm) {
let myAlarmNotifContent = UNMutableNotificationContent()
myAlarmNotifContent.title = "Reminder"
myAlarmNotifContent.body = alarm.activity
myAlarmNotifContent.sound = UNNotificationSound.default()
if alarm.repeatDays.count == 1 {
} else {
for index in 1...alarm.repeatDays.count {
createNotif(date: alarm.date, weekDay: index, content: myAlarmNotifContent)
}
}
}
private func createNotif(date: Date, weekDay: Int, content: UNNotificationContent) {
var dateComponent = DateComponents()
dateComponent.weekday = weekDay
dateComponent.hour = Calendar.current.dateComponents([.hour], from: date).hashValue
dateComponent.minute = Calendar.current.dateComponents([.minute], from: date).hashValue
let myAlarmTrigger = UNCalendarNotificationTrigger(dateMatching: dateComponent, repeats: true)
setupNotificationSettings()
let identifier = "Your-Notification"
let request = UNNotificationRequest(identifier: identifier, content: content, trigger: myAlarmTrigger)
let center = UNUserNotificationCenter.current()
center.add(request, withCompletionHandler: { (error) in
if error != nil {
//TODO: Handle the error
}
})
}
Basically what I have found is that you can set a separate notification for each day you want the alarm to trigger. For example, you want every Monday and every Tuesday, so create a date component for each day and add it to the trigger. It is not perfect but is a solution that I think is better then calculating time intervals.
I'm trying to figure out how to determine whether today is the anniversary of an NSCalendar item. Everything I've found compares a specific date's month, day, year to another specific month, day, and year. The granularity works against me, as the first thing it compares is the year.
Here's what I've got so far. I've read the documentation, but I'm missing something (basic). What is it?
// get the current date
let calendar = NSCalendar.currentCalendar()
var dateComponents = calendar.components([.Month, .Day], fromDate: NSDate())
let today = calendar.dateFromComponents(dateComponents)
var birthDates = [NSDate]()
let tomsBirthday = calendar.dateWithEra(1, year: 1964, month: 9, day: 3, hour: 0, minute: 0, second: 0, nanosecond: 0)
birthDates.append(tomsBirthday!)
let dicksBirthday = calendar.dateWithEra(1, year: 1952, month: 4, day: 5, hour: 0, minute: 0, second: 0, nanosecond: 0)
birthDates.append(dicksBirthday!)
let harrysBirthday = calendar.dateWithEra(1, year: 2015, month: 10, day: 27, hour: 0, minute: 0, second: 0, nanosecond: 0)
birthDates.append(harrysBirthday!)
for birthday in birthDates {
// compare the month and day to today's month and day
// if birthday month == today's month {
// if birthday day == today's day {
// do something
// }
}
To make the date comparison, while treating February 29 as March 1 in non-leap years, you need to use the month and day components of the person's birthday to construct an NSDate in the current year.
Also, don't use midnight as time when constructing an NSDate for comparing dates. Some days don't have a midnight in some time zones. Use noon instead.
struct Person {
let name: String
let birthYear: Int
let birthMonth: Int
let birthDay: Int
}
let people = [
Person(name: "Tom", birthYear: 1964, birthMonth: 9, birthDay: 3),
Person(name: "Dick", birthYear: 1952, birthMonth: 4, birthDay: 5),
Person(name: "Harry", birthYear: 2015, birthMonth: 10, birthDay: 28)
]
let calendar = NSCalendar.autoupdatingCurrentCalendar()
let todayComponents = calendar.components([.Era, .Year, .Month, .Day], fromDate: NSDate())
todayComponents.hour = 12
let todayNoon = calendar.dateFromComponents(todayComponents)
for person in people {
let components = todayComponents.copy() as! NSDateComponents
// DON'T copy person.birthYear
components.month = person.birthMonth
components.day = person.birthDay
let birthdayNoon = calendar.dateFromComponents(components)
if todayNoon == birthdayNoon {
print("Happy birthday, \(person.name)!")
}
}