I am trying to get the dates for the whole week. I can currently get the current date, but I want to add 6 days to that so I can get a list of the whole week. How would I do that? Any help is appreciated!
let now = NSDate()
override func viewDidLoad() {
super.viewDidLoad()
print("Now \(now)") //prints current date
}
A quick and easy way of doing it:
if let calendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian) {
var thisWeek = [NSDate]()
for i in 0...6 {
if let nextDay = calendar.dateByAddingUnit(NSCalendarUnit.Day , value: i, toDate: NSDate(), options: .MatchStrictly) {
thisWeek.append(nextDay)
}
}
}
Related
I want to add / or subtract a day from a selected date. The user selects for example 09-10-2019, when user press a button, the date should be 10-10-2019.
I am not trying to add or reduce a day from Current date.
On the previous screen , I have a variable -> Which is user selected and is not static
selecteddate = "09.10.2019"
I declared it as a global variable so it can be used in several screens, so in this screen , I get this 'selected date'.
I have 3 UIButtons. yesterdaybutton, selecteddatebutton and tomorrowbutton
When user presses yesterday button then 1 day should be reduced from
'selecteddate' variable
When user presses tomorrow button then 1 day should be added to
'selecteddate' variable.
I followed what the answer said. But unfortunately my selecteddate was a string and I needed to sent string to api in its format.
So , I did the following.
let dateFormattera = DateFormatter()
dateFormattera.dateFormat = "dd.MM.yyyy"
let date = dateFormattera.date(from: datetoday)
let newdate = Calendar.current.date(byAdding: .day, value: +1, to: date!)
let dateFormatterb = DateFormatter()
dateFormatterb.dateFormat = "dd.MM.yyyy"
let tomorrowdate = dateFormatterb.string(from: newdate!)
let dateFormatterx = DateFormatter()
let day = dateFormatterx.date(from: datetoday)
let newday = Calendar.current.date(byAdding: .day, value: +1, to: date!)
let dateFormattery = DateFormatter()
dateFormattery.dateFormat = "EEE"
let tomorrowday = dateFormattery.string(from: newdate!)
There might be junk code in this, but this made everything work as it should. This gets the DATE and DAY. I had to use this because converting string to date added +1 day to the date (due to UTC timing 18:00) despite doing -1 or +1
I suggest that you use:
Calendar.current.date(byAdding: .day, value: 1, to: selecteddate)
This will add one day to selecteddate
Then, if you have 2 buttons, as you have explained, you could set a tag to each button:
yesterdaybutton.tag = -1
tomorrowbutton.tag = 1
We will use each button's tag to add or reduce days from selecteddate
So, both buttons will use this:
#IBAction func buttonAction(_ sender: UIButton) {
let newDate = Calendar.current.date(byAdding: .day, value: sender.tag, to: selecteddate)
}
You can create a method like below that calculates the date.
func calculateDate(fromDate date: Date, withUnit value: Int) -> Date? {
return Calendar.current.date(byAdding: .day, value: value, to: date)
}
How to use it?
When yesterday button is selected then you need call method like below...
if let date = calculateDate(fromDate: selecteddate, withUnit: -1) {
print(date)
} else {
print("date is nil. may be due to different formats of dates")
}
When tomorrow button is selected then you need call method like below...
if let date = calculateDate(fromDate: selecteddate, withUnit: 1) {
print(date)
} else {
print("date is nil. may be due to different formats of dates")
}
Note: Please use date format if required. The date format should be same for all dates.
You still need to convert your string to a concrete object which in your case is Date. To it you can add or subtract components as you wish. In your case those are days alone. Check the following:
func addDays(_ days: Int, toDate dateString: String?) throws -> String {
guard let dateString = dateString else { throw NSError(domain: "Add days", code: 400, userInfo: ["dev_message": "String is null"]) }
let formatter = DateFormatter()
formatter.dateFormat = "dd'.'MM'.'yyyy"
// formatter.dateFormat = "MM'.'dd'.'yyyy" // Not sure which
guard let date = formatter.date(from: dateString) else { throw NSError(domain: "Add days", code: 400, userInfo: ["dev_message": "Incorrect date format. Expecting \(formatter.dateFormat!)"]) }
guard let newDate = formatter.calendar.date(byAdding: {
var components: DateComponents = DateComponents()
components.day = days
return components
}(), to: date) else { throw NSError(domain: "Add days", code: 400, userInfo: ["dev_message": "Could not add days for some reason"]) }
return formatter.string(from: newDate)
}
A usage I tried was:
print(try! addDays(1, toDate: "09.10.2019")) // Prints 10.10.2019
print(try! addDays(30, toDate: "09.10.2019")) // Prints 08.11.2019
print(try! addDays(-1, toDate: "09.10.2019")) // Prints 08.10.2019
So in your case you need addDays(1, toDate: "09.10.2019")to get to next day and addDays(-1, toDate: "09.10.2019") for previous day.
I have been struggling making a countdown in Swift where it shows only the days left until some date where the input is the DatePicker... I have creo experience with Swift so, I have been struggling for a while. I tried some similar answers here but didn't work, I watched a tutorial but is a normal countdown with months, days, minutes and seconds, this is the code.
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var timeLabel: UILabel!
let formatter = DateFormatter()
let userCleander = Calendar.current;
let requestedComponent : Set<Calendar.Component> = [
Calendar.Component.month,
Calendar.Component.day
]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(timePrinter), userInfo: nil, repeats: true)
timer.fire()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func timeCalculator(dateFormat: String, endTime: String, startTime: Date = Date()) -> DateComponents {
formatter.dateFormat = dateFormat
let _startTime = startTime
let _endTime = formatter.date(from: endTime)
let timeDifference = userCleander.dateComponents(requestedComponent, from: _startTime, to: _endTime!)
return timeDifference
}
func timePrinter() -> Void {
let time = timeCalculator(dateFormat: "MM/dd/yyyy a", endTime: "12/25/2018 a")
timeLabel.text = "\(time.month!) Months \(time.day!) Days"
}
}
Several things: Don't use strings to compare dates. Use Date objects and Calendar operations. (More on that in a second.)
Don't run a timer once a second. Save the current date to user defaults. When your app is launched, compare the saved date to the current date and see if the day has changed.
When running, listen for UIApplicationSignificantTimeChange notifications, and when you get one, check to see if the date has changed.
As for comparing the current date to the user-selected date, you've got the right idea using dateComponents(_:from:to:), but you should pass in components of just [.day].
EDIT:
Code like this would do the trick:
override func viewDidLoad() {
super.viewDidLoad()
//Set up the date picker to pick dates, not dates & times
datePicker.datePickerMode = .date
//Force the date picker to use midnight today as it's base date and
//to pick a date at least 1 day in the future
guard let today = Calendar.current.date(bySettingHour: 0, minute: 0, second: 0, of: Date()),
let tomorrow = Calendar.current.date(byAdding: .day, value: 1, to: today)
else {
return
}
datePicker.minimumDate = tomorrow
datePicker.date = tomorrow
}
#IBAction func datePickerChanged(_ sender: UIDatePicker) {
let future = datePicker.date
//Use midnight today as the starting date
guard let today = Calendar.current.date(bySettingHour: 0, minute: 0, second: 0, of: Date()) else { return }
//Calculate the number of days between today and the user's chosen day.
let difference = Calendar.current.dateComponents([.day], from: today, to: future)
guard let days = difference.day else { return }
let ess = days > 1 ? "s" : ""
infoLabel.text = "That date is \(days) day\(ess) away."
}
I did a lot of searching through Stackoverflow but I havent found answer for my problem.
I am developing an app and I get JSON data for some events. What I get is the start time of the event and the duration of the event. All data in recived as String.
In one screen of the app I would like to show only the event that are currently going on.
for example:
Class Event {
var startTime: String?
var duration: String?
}
let event1 = Event()
event1.starTime = "12-12-2016, 10:50 AM"
event1.duration = "50min"
let event2 = Event()
event2.starTime = "12-12-2016, 09:50 AM"
event2.duration = "40min"
let event3 = Event()
event3.starTime = "12-12-2016, 10:10 AM"
event3.duration = "90min"
let allEvents = [event1, event2, event3]
and let say the the current date and time is 12-12-2016, 11:00AM. How can I filter/find events in allEvents that are still going on if we compare them to the current date?
Thank you in advance.
EDIT: My solution
I created method for converting dateString and durationString to startDate: Date and endDate: Date
static func convertDateStringAndDurationStringToStartAndEndDate(date: String, duration: String) -> (start: Date, end: Date)? {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
guard let startDate = dateFormatter.date(from: date) else { return nil }
guard let duration = Int(duration) else { return nil }
// recived interval is in minutes, time interval must be calculated in seconds
let timeInterval = TimeInterval(Int(duration) * 60 )
let endDate = Date(timeInterval: timeInterval, since: startDate)
return (startDate, endDate)
}
For filtering I have created separated method. In my case I am using Realm database, but you will get the point.
static func filterResultsForNowPlaying(results: Results<Show>?) -> Results<Show>? {
let currentDate = NSDate()
let datePredicate = NSPredicate(format: "startDate <= %# AND %# <= endDate", currentDate, currentDate)
let filteredShows = results?.filter(datePredicate)
return filteredShows
}
You will need to convert them into dates, using DateFormatter, and then use a .filter over the array and have it match on if the current date is in range.
If you have the ability to change the Event class, you can greatly simplify your code if you replace your Event class with the DateInterval class, which does the same thing:
let minutes = 60;
let formatter = DateFormatter()
formatter.dateFormat = "MM-dd-yyyy"
let event1 = DateInterval(
start: formatter.date(from: "12-12-2016")!,
duration: TimeInterval(20 * minutes)
)
let now = Date()
if (event1.contains(now)) {
print("Event 1 is still active")
}
I am new in iOS and programming and I need somehow to get an array from the first day of current month till today. And one array for past 3 months till today, but I have no idea how to do that, please any help or ideas?
I checked about this to get the first day of month:
extension Date {
func startOfMonth() -> Date? {
let comp: DateComponents = Calendar.current.dateComponents([.year, .month, .hour], from: Calendar.current.startOfDay(for: self))
return Calendar.current.date(from: comp)!
}
but it works only in a ViewController, what to do if do that in other part of my project? and also I have no idea how to iterate the array to get all the days between first day and today...
EDIT
I made something like this, but it gives ma an infinite loops.. what am I doing wrong?
func weatherDatesFromCurrentDayMonth() -> [Any] {
var date = Date()
let currentCalendar = Calendar.current
var dateComponents = DateComponents()
dateComponents.month = -1
// dateComponents.day = 1
let endingDate = Calendar.current.date(byAdding: dateComponents, to: date)
print("\(endingDate!)")
var datesArray = Array<Any>()
while date.compare(endingDate!) != ComparisonResult.orderedAscending
{
var dateComponents = DateComponents()
dateComponents.day = 1
date = Calendar.current.date(byAdding: dateComponents, to: date)!
datesArray.append(date)
print("\(datesArray)")
}
return [datesArray]
}
You're having an endless loop because at the beginning your endingDate is already one month ago and date is now. Since inside the loop you only increment date it will never always be after endingDate and thus your condition is always true
Try this code:
func weatherDatesFromCurrentDayMonth() -> [Date] {
let now = Date()
var currentDate = previousMonth(date: now)
var datesArray = [Date]()
while currentDate < now {
datesArray.append(currentDate)
currentDate = nextDay(date:currentDate)
}
print("result: \(datesArray)")
return datesArray
}
func nextDay(date: Date) -> Date {
var dateComponents = DateComponents()
dateComponents.day = 1
return Calendar.current.date(byAdding: dateComponents, to: date)!
}
func previousMonth(date: Date) -> Date {
var dateComponents = DateComponents()
dateComponents.month = -1
return Calendar.current.date(byAdding: dateComponents, to: date)!
}
I have a core data entity.The creation date of each entry is saved as an attribute in the entity.I want to display all entries since last sunday to the current day.How can I perform this?.Should I also add the the day of entry as an attribute???
this will help you to get the date of the last sunday adjust the value by which day of the week you are on then compare the retrieved dates with this date
extension NSDate {
func dayOfWeek() -> Int? {
if
let cal: NSCalendar = NSCalendar.currentCalendar(),
let comp: NSDateComponents = cal.components(.Weekday, fromDate: self) {
return comp.weekday
} else {
return nil
}
}
}
let calendar = NSCalendar.currentCalendar()
let lastSundayDate = calendar.dateByAddingUnit(.Day , value: -NSDate().dayOfWeek()!, toDate: NSDate(), options: [])
The recommended way to find the last sunday is nextDateAfterDate:components:options: of NSCalendar searching backwards
let components = NSDateComponents()
components.weekday = 1 // 1 = sunday
let lastSunday = NSCalendar.currentCalendar().nextDateAfterDate(NSDate(), matchingComponents: components, options: [.SearchBackwards, .MatchNextTime])
Set the fetch predicate to consider dates after (>) lastSunday