Swift: Next instance of certain time on soonest date - swift

I'm working with Swift 2.1 to build an app that sets repeated reminders. This consists mainly of two parts:
The user can select a time at which reminders must begin (e.g. 09:00)
The user can choose to have it repeat every X hours (e.g. if it's six hours, then the reminders would be set at 09:00, 15:00, 21:00, 03:00)
I'm using CVCalendarKit to manipulate certain date units, so part 2 (adding X hours every time) isn't the trouble I'm having.
What I'm trying to figure out is if there's an easy way to create an instance of NSDate with the soonest instance of a certain time.
So, assuming today is 13th of February 2016,
If it's 8:59, the NSDate created should be 2016-02-13 09:00:00
If it's 9:01, the NSDate created should be 2016-02-14 09:00:00
Many thanks in advance.

You can use NSCalendar.nextDateAfterDate()
let calendar = NSCalendar.currentCalendar()
let now = NSDate()
let nextTime = calendar.nextDateAfterDate(now,
matchingHour: 9,
minute: 0,
second: 0,
options: NSCalendarOptions.MatchNextTime)
If you aren't using the open source Swift Foundation libraries, this only works on iOS 8+ or OS X 10.9+

Watch out for changes in daylight savings time.
Quite soon there will a day where one hour is missing. In that case you (or your user) must make two decisions: 1. What happens if the date you are interested in doesn't exist? (For example, there will be one day in the year in the UK where "2:30 am on the next day" doesn't exist). 2. What do you mean by "every six hours"? On one day of the year, "6 hours after 21:00" is "04:00" on the next day.

Related

Why does SYSTEMTIME::wDayOfWeek begin with 0 for sunday?

Can anyone here tell me why the week begins at 0 for sunday with SYSTEM_TIME::wDayOfWeek ? Here in Germany the week begins at monday. But maybe I'm missing that for other cultures the week begins at sunday.
The modern calendar was sponsored by Pope Gregory XIII. So regardless of one's personal beliefs about religion, it's necessary to look at what the designers of the Gregorian calendar believed:
In Genesis, the creation takes six days followed by one day of rest. It doesn't actually matter whether those were literal days, because the follow-up commandment to rest on each seventh day was talking about a literal day. That seventh day on which to rest was called "Sabbath" by the Jews.
In the gospels, the time of week isn't left to the imagination. Perfume could not be applied to the body of the Messiah as he was buried (as it was a feast day) or on the next day (as it was a Sabbath), so the women arrived at the tomb on the morning following the Sabbath, and recorded that they found it empty and thereafter spoke to a resurrected Messiah.
In honor of these two events in which the designers of and early adherents to the Gregorian calendar deeply believed, they made a weekend out of (a) the Sabbath (our Saturday), which was by definition the seventh day of one week, and (b) the weekday corresponding to resurrection (our Sunday), which therefore had to be the first day of the next week.
And that's why, in the Gregorian calendar, the week starts on Sunday. This is the system followed in the USA where the majority of OS APIs were designed, including the Windows API.

What day of the week dose the week start with?

Maybe I'm overthinking this. I want to send a local notification every Monday at 9am until some condition is met. I know this can be done by setting the weekday and hour components of a DateComponents. The problem I'm having is the value would I pass to weekday depends on the Calendar the DateComponents is using. Which if I understand correctly depends on the user's settings. For instance if the user's calendar week starts on a Sunday I would pass a 1 to weekday but if the week starts on a Saturday I would pass 2.
My question is how do I account for things like timezone, daylight savings, and week start day?
Weekday units are the number go 1 through 7, where 1 is Sunday, 2 is Monday... And this won't never change.
When user changes setting, only the calendar.firstWeekday will change.
E.g. if the user's calendar week starts on Sunday, firstWeekday = 1 else if start on Monday, firstWeekday = 2

Why is Date.getMinutes() returning 2 for the time 4:00 PM?

I'm creating a customized function that does some calculations for a given time.
When a time is entered in a cell, for example 4:00 PM, this is automatically converted into a date, in this case 12/30/1899 16:00:00 and when the function getTheMinutes() is called, it returns 2 instead of 0.
function getTheMinutes(dateTime){
return dateTime.getMinutes();
}
The behavior of the function is different if it's used for a most recent date like 5/1/2019 16:00:00.
I want the user to be able to just write a time in a cell then use the customized function in another cell. Please let me know your thoughts.
Now that you have indicated the time zone for your spreadsheet I can confirm what #RobG deduced almost a day ago, which is that Guatemala adjusted its difference relative to UTC. Something you have confirmed is treated as by two minutes with effect from October 5, 1918.
More specifically, the adjustment was of 2 minutes and 4 seconds and effective from 03:00 that day:
(Source IANA Version 2019b file northamerica.)
There have been very many such minor adjustments around the world over the years (even between towns in the same country) and adjustments continue, though usually of a whole hour – between 'standard' and Summer time. Sheets has very properly recognised that "normal arithmetic" 'does not work' across such a transition and while noon yesterday to noon today for example is normally, for any one specific location, a difference of 24 hours it is often 23 hours or 25 hours on the day that clocks go forward/back.
And the moral of the story is to beware of obliging Sheets to assume, for want of a specific date, that is has the index number 0 - i.e. is December 30, 1899.
I made some testing, and I found out that the formula is giving a wrong result any minute before 10/5/1918 0:03:00, from that DateTime on, the formula is working as expected.
Here is my sheet https://docs.google.com/spreadsheets/d/1psm8_GJYRczO53TILJCOzo0p4GpnS-ooiGWqOJrC8ZU/edit?usp=sharing
I would need to do a date validation in my customized formula to make it useful. I don't know why google sheets is choosing that date as default when just a time is typed in a cell, I think it should be improved.

How to get last day of the month in Cocoa?

I would like to make a function that input a NSDate and output the last date of the month. Do you guys know how to do it in Cocoa?
It's the day before the first day of the next month. Add a month, set the day to 1, subtract a day. For setting the day to 1, you'll find it easier to go via NSCalendar. See here for details.
If you're doing date computations, you should always use NSCalendar and related classes, because that's the only way to be forward-compatible with changes to calendars, support for non-"standard" calendars, and so on.
Read the Date and Time Programming Guide section on Calendrical Calculations to get an idea of how these classes work together.

Is there a Haskell library for dates?

Is there a function in Haskell that will allow me to enter component of a date (like a string representation or day month year components) that I can get information from (like day of week, days in a month, etc.)?
I've looked online and it looks like there are a lot of custom libraries, but I'm hoping there's one in the standard prelude library of ghci 10.6.4 that's just not well documented?
Are Data.Time.Calendar and Data.Time.Format in the time library sufficient?
You can parse a string representation of a date and get the length of a month using gregorianMonthLength. Not sure about day of the week, though you could format the date as a string using a format that just displays the week day.
A quick Google search turns up this, which may be what you want. It lets you parse strings representing dates and extract information from them.
You can find the day of the week with mondayStartWeek or sundayStartWeek, depending on whether you think a week starts on Monday, or on Sunday. Both functions are in Data.Time.Calendar.OrdinalDate.
λ> snd $ mondayStartWeek $ fromGregorian 2017 10 3
2
In the above example, the return value is 2, which indicates the second day of the week. Since the function is called mondayStartWeek, Monday is the first day, so 2 corresponds to Tuesday. This is true of October 3, 2017.
A warning regarding week numbers
Both functions return a tuple, where the second element is the week day. As far as I can tell, that should be trustworthy.
The first element, however, is the week number of the year. Be careful with that, because the rules for week numbering are political. If I remember correctly, in USA, week 1 is the week that contains January 1. That's not the case in Denmark, where I live. Here, week 1 is the first week where Thursday falls in the new year. This can mean that December 31 can fall in week 1 of the next year. IIRC, this is the rule for many other European countries. Some years, the American and the European week numbers align, but some years, they don't.