Programmatically implemented
set limit
let calendar = Calendar.current
let currentDate = Date()
var components = DateComponents()
components.calendar = calendar
components.year = -100
let minDate = calendar.date(byAdding: components, to: currentDate)!
components.year = -7
let maxDate = calendar.date(byAdding: components, to: currentDate)!
datePicker.minimumDate = minDate
datePicker.maximumDate = maxDate
method call on value change
#objc fileprivate func datePickerChanged() {
print(datePicker.date)
}
Target
datePicker.addTarget(self, action: #selector(datePickerChanged), for: .valueChanged)
You can fix this issue by adding the following
datePicker.timeZone = TimeZone(secondsFromGMT: 0)
Related
I managed to get data query with "nextDate" property of type Date() in a particular month. In other words all data with dates within that particular month will appear on my tableview when queried. Using the code below and with tweaks I also managed to extract data from the previous and next month.
func loadMonthEvents() {
let date = Date()
let calendar = Calendar.current
var beginningOfMonth: Date?
var endOfMonth: Date?
beginningOfMonth = calendar.dateInterval(of: .month, for: date)?.start
endOfMonth = calendar.dateInterval(of: .month, for: date)?.end
monthEvents = realm.objects(Events.self).filter("nextDate BETWEEN %#", [beginningOfMonth, endOfMonth]).sorted(byKeyPath: "nextDate", ascending: true)
}
Now I want to be able to separate those data according to the week of the month. In my tableView the will be 5 separate headers representing week 1, week 2, week 3, week 4 and week 5(if any). Each separate header will show only event for that week. I tried to apply the weekOfMonth in calendar but it just dont work. Thank you in advance.
You could get the range of weeks from your two dates by doing
let w1 = calendar.dateComponents([.weekOfYear], from: beginningOfMonth!)
print(w1.weekOfYear)
let w2 = calendar.dateComponents([.weekOfYear], from: endOfMonth!)
print(w2.weekOfYear)
And then you could do the same for the date of each event to group the event to a specifik week
Here is the snippet to find out first and last day of week . You can do this by adding .weekOfMonth to the date component . Go through this official link and apply accordingly as per your requirement for fetch.
Now i had added two functions / or two button action through which you can get previous week and next week of the month.
var currentDate = Date()
func weekCalculation()
{
let calendar = NSCalendar.current
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
// dateFormatter.dateStyle = .medium
var componentsNow = calendar.dateComponents([.year, .month, .weekOfMonth, .weekday], from: currentDate)
componentsNow.setValue(1, for: .weekday)
firstDayOfWeek = calendar.date(from: componentsNow)!
print(firstDayOfWeek)
componentsNow.setValue(7, for: .weekday)
lastDayOfWeek = calendar.date(from: componentsNow)!
print(lastDayOfWeek)
let addDaysCount = 0
var comps = DateComponents()
comps.setValue(addDaysCount, for: .weekday)
var comps1 = DateComponents()
comps1.setValue(-6, for: .day)
let newDate1 = calendar.date(byAdding: comps1, to: lastDayOfWeek)
let newDate2 = calendar.date(byAdding: comps, to: lastDayOfWeek)
// print(newDate1!,newDate2!)
let firstDay = dateFormatter.string(from: newDate1!)
let lastDay = dateFormatter.string(from: newDate2!)
// ShowBanner(title: "", subtitle: firstDay)
let dF = DateFormatter()
dF.dateFormat = "d MMMM yyyy"
let fDayToShow = dF.string(from: newDate1!)
let lDayToShow = dF.string(from: newDate2!)
let dateString = String(format: "%# - %#",fDayToShow,lDayToShow)
print(firstDay,lastDay)
}
#IBAction func nextWeekBtnPressed(sender: UIButton)
{
let calendar = NSCalendar.current
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
// dateFormatter.dateStyle = .medium
let dF = DateFormatter()
dF.dateFormat = "d MMMM yyyy"
let addDaysCount = 7
var comps = DateComponents()
comps.setValue(addDaysCount, for: .weekday)
var comps1 = DateComponents()
comps1.setValue(3, for: .day)
let newDate1 = calendar.date(byAdding: comps1, to: lastDayOfWeek)
let newDate2 = calendar.date(byAdding: comps, to: lastDayOfWeek)
let firstDay = dateFormatter.string(from: newDate1!)
let lastDay = dateFormatter.string(from: newDate2!)
let fDayToShow = dF.string(from: newDate1!)
let lDayToShow = dF.string(from: newDate2!)
//print(firstDay,lastDay)
let dateString = String(format: "%# - %#",fDayToShow,lDayToShow)
//print(dateString)
weekCalculation()
}
#IBAction func previousWeekBtnPressed(sender: UIButton)
{
let calendar = NSCalendar.current
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
// dateFormatter.dateStyle = .medium
let addDaysCount = -7
var comps = DateComponents()
comps.setValue(addDaysCount, for: .weekday)
var comps1 = DateComponents()
comps1.setValue(-10, for: .day)
let newDate1 = calendar.date(byAdding: comps1, to: lastDayOfWeek)
let newDate2 = calendar.date(byAdding: comps, to: lastDayOfWeek)
let firstDay = dateFormatter.string(from: newDate1!)
let lastDay = dateFormatter.string(from: newDate2!)
let dF = DateFormatter()
dF.dateFormat = "d MMMM yyyy"
let fDayToShow = dF.string(from: newDate1!)
let lDayToShow = dF.string(from: newDate2!)
let dateString = String(format: "%# - %#",fDayToShow,lDayToShow)
weekCalculation()
}
I have Date Picker
I already set the current Date, and i want to make User cannot scroll back to previous date? is it allowed?
As the documentation says here
you have just to set the option minimumDate of your UIDatePicker.
This is an example
var datePicker = UIDatePicker() //your UIDatePicker
datePicker.minimumDate = Date() //the minimum date is now. Only future date is allowed
Another case is the following
var datePicker = UIDatePicker() //your UIDatePicker
//create a gregorian calendar
let calendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
// set the timezone
calendar.timeZone = NSTimeZone(name: "UTC")!
// create and set the component (for your minimum date value)
let components: NSDateComponents = NSDateComponents()
components.calendar = calendar
components.year = -100
// obtain the minimum NSDate, according to the defined components
//it will result as the difference of the years (components.year) from now (NSDate())
let minDate100YearsAgo: NSDate = calendar.dateByAddingComponents(components, toDate: NSDate(), options: NSCalendarOptions(rawValue: 0))!
//then you add this to the UIDatePicker
datePicker.minimumDate = minDate100YearsAgo
This is an example to how to do it in Swift 2.2:
// a global var
var datePicker = UIDatePicker()
// UIDatePicker settings:
let currentDate: NSDate = NSDate()
let calendar: NSCalendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
calendar.timeZone = NSTimeZone(name: "UTC")!
let components: NSDateComponents = NSDateComponents()
components.calendar = calendar
components.year = -18
let minDate: NSDate = calendar.dateByAddingComponents(components, toDate: currentDate, options: NSCalendarOptions(rawValue: 0))!
components.year = -150
let maxDate: NSDate = calendar.dateByAddingComponents(components, toDate: currentDate, options: NSCalendarOptions(rawValue: 0))!
datePicker.dateOfBirthUIDatePicker.minimumDate = minDate
datePicker.dateOfBirthUIDatePicker.maximumDate = maxDate
At Swift 3:
var datePicker = UIDatePicker()
datePicker.minimumDate = Date()
I am trying this code but it is not working.
thanks to all.
I am using uidatepicker with select minimumDate. but require current date with additional 15 days in datepicker swift 2.0.
override func viewDidLoad() {
let datePickerView:UIDatePicker = UIDatePicker()
datePickerView.datePickerMode = UIDatePickerMode.Date
sender.inputView = datePickerView
datePickerView.minimumDate = datePickerView.date
//datePickerView.maximumDate = datePickerView.date
datePickerView.addTarget(self, action: #selector(BookAppointmentView.datePickerValueChanged(_:)), forControlEvents: UIControlEvents.ValueChanged)
}
func datePickerValueChanged(sender:UIDatePicker)->NSDate {
let baseDate:NSDate = NSDate()
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
DatePickerField.text = dateFormatter.stringFromDate(sender.date)
print("date of bookAppointment\(DatePickerField.text!)")
return newDate!
}
There are multiple ways to accomplish this.
dateByAddingTimeInterval is one, in which you add time in seconds:
datepickerView.minimumDate = NSDate() // current date
datepickerView.maximumDate = NSDate().dateByAddingTimeInterval(1296000) // date + 15 days
You can also do:
datepickerView.minimumDate = NSDate() // current date
let maxDateComponent = NSDateComponents()
maxDateComponent.day = //days you want to add
datePickerView.maximumDate = NSCalendar.currentCalendar().dateByAddingComponents(maxDateComponent, toDate: NSDate(), options: NSCalendarOptions.init(rawValue: 0))
In which you add the time in days.
I hope this extension method helps
extension NSDate {
func dateByAddingDays(days:Int) -> NSDate? {
let c:NSDateComponents = NSDateComponents()
c.day = days;
return NSCalendar.currentCalendar().dateByAddingComponents(c, toDate: self, options: [])
}
}
this code is not tested. but i have used dateByAddingComponents in some cases
If I create a Date() to get the current date and time, I want to create a new date from that but with different hour, minute, and zero seconds, what's the easiest way to do it using Swift? I've been finding so many examples with 'getting' but not 'setting'.
Be aware that for locales that uses Daylight Saving Times, on clock change days, some hours may not exist or they may occur twice. Both solutions below return a Date? and use force-unwrapping. You should handle possible nil in your app.
Swift 3+ and iOS 8 / OS X 10.9 or later
let date = Calendar.current.date(bySettingHour: 9, minute: 30, second: 0, of: Date())!
Swift 2
Use NSDateComponents / DateComponents:
let gregorian = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
let now = NSDate()
let components = gregorian.components([.Year, .Month, .Day, .Hour, .Minute, .Second], fromDate: now)
// Change the time to 9:30:00 in your locale
components.hour = 9
components.minute = 30
components.second = 0
let date = gregorian.dateFromComponents(components)!
Note that if you call print(date), the printed time is in UTC. It's the same moment in time, just expressed in a different timezone from yours. Use a NSDateFormatter to convert it to your local time.
swift 3 date extension with timezone
extension Date {
public func setTime(hour: Int, min: Int, sec: Int, timeZoneAbbrev: String = "UTC") -> Date? {
let x: Set<Calendar.Component> = [.year, .month, .day, .hour, .minute, .second]
let cal = Calendar.current
var components = cal.dateComponents(x, from: self)
components.timeZone = TimeZone(abbreviation: timeZoneAbbrev)
components.hour = hour
components.minute = min
components.second = sec
return cal.date(from: components)
}
}
//Increase the day & hours in Swift
let dateformat = DateFormatter()
let timeformat = DateFormatter()
dateformat.dateStyle = .medium
timeformat.timeStyle = .medium
//Increase Day
let currentdate = Date()
let currentdateshow = dateformat.string(from: currentdate)
textfield2.text = currentdateshow
let myCurrentdate = dateformat.date(from: dateTimeString)!
let tomorrow = Calendar.current.date(byAdding: .day, value: 1, to: myCurrentdate) // Increase 1 Day
let tomorrowday = dateformat.string(from: tomorrow!)
text3.text = tomorrowday
text3.isEnabled = false
//increase Time
let time = Date()
let currenttime = timeformat.string(from: time)
text4.text = currenttime
let mycurrenttime = timeformat.date(from: currenttime)!
let increasetime = Calendar.current.date(byAdding: .hour, value: 2, to: mycurrenttime) //increase 2 hrs.
let increasemytime = timeformat.string(from: increasetime!)
text5.text = increasemytime
I was facing the struggle of making a timer app, so I thought that now that I solved it I could help others who face the problem. So basically this app counts down to a specific date from the current time. As stack overflow allows a Q and A format I hope that can help you. See the comments for explanations.
Cleaned up and updated with countdown computed on a timer and leading zero String format.
let futureDate: Date = {
var future = DateComponents(
year: 2020,
month: 1,
day: 1,
hour: 0,
minute: 0,
second: 0
)
return Calendar.current.date(from: future)!
}()
var countdown: DateComponents {
return Calendar.current.dateComponents([.day, .hour, .minute, .second], from: Date(), to: futureDate)
}
#objc func updateTime() {
let countdown = self.countdown //only compute once per call
let days = countdown.day!
let hours = countdown.hour!
let minutes = countdown.minute!
let seconds = countdown.second!
countdownLabel.text = String(format: "%02d:%02d:%02d:%02d", days, hours, minutes, seconds)
}
func runCountdown() {
Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(updateTime), userInfo: nil, repeats: true)
}
Here is the solution of how I managed to create a countdown timer to a specific NSDate, for SO allows Q and A Style Answers.
// here we set the current date
let date = NSDate()
let calendar = NSCalendar.currentCalendar()
let components = calendar.components(.CalendarUnitHour | .CalendarUnitMinute | .CalendarUnitMonth | .CalendarUnitYear | .CalendarUnitDay, fromDate: date)
let hour = components.hour
let minutes = components.minute
let month = components.month
let year = components.year
let day = components.day
let currentDate = calendar.dateFromComponents(components)
// here we set the due date. When the timer is supposed to finish
let userCalendar = NSCalendar.currentCalendar()
let competitionDate = NSDateComponents()
competitionDate.year = 2015
competitionDate.month = 6
competitionDate.day = 21
competitionDate.hour = 08
competitionDate.minute = 00
let competitionDay = userCalendar.dateFromComponents(competitionDate)!
// Here we compare the two dates
competitionDay.timeIntervalSinceDate(currentDate!)
let dayCalendarUnit: NSCalendarUnit = (.CalendarUnitDay | .CalendarUnitHour | .CalendarUnitMinute)
//here we change the seconds to hours,minutes and days
let CompetitionDayDifference = userCalendar.components(
dayCalendarUnit, fromDate: currentDate!, toDate: competitionDay,
options: nil)
//finally, here we set the variable to our remaining time
var daysLeft = CompetitionDayDifference.day
var hoursLeft = CompetitionDayDifference.hour
var minutesLeft = CompetitionDayDifference.minute
Hope that helps you guys if you're facing the same struggle as I have
Cleaned up/updated for latest Swift version of the accepted answer.
// here we set the current date
let date = NSDate()
let calendar = Calendar.current
let components = calendar.dateComponents([.hour, .minute, .month, .year, .day], from: date as Date)
let currentDate = calendar.date(from: components)
let userCalendar = Calendar.current
// here we set the due date. When the timer is supposed to finish
let competitionDate = NSDateComponents()
competitionDate.year = 2017
competitionDate.month = 4
competitionDate.day = 16
competitionDate.hour = 00
competitionDate.minute = 00
let competitionDay = userCalendar.date(from: competitionDate as DateComponents)!
//here we change the seconds to hours,minutes and days
let CompetitionDayDifference = calendar.dateComponents([.day, .hour, .minute], from: currentDate!, to: competitionDay)
//finally, here we set the variable to our remaining time
let daysLeft = CompetitionDayDifference.day
let hoursLeft = CompetitionDayDifference.hour
let minutesLeft = CompetitionDayDifference.minute
print("day:", daysLeft ?? "N/A", "hour:", hoursLeft ?? "N/A", "minute:", minutesLeft ?? "N/A")
//Set countdown label text
countDownLabel.text = "\(daysLeft ?? 0) Days, \(hoursLeft ?? 0) Hours, \(minutesLeft ?? 0) Minutes"
This worked for me.
The only thing that troubles me is that it doesn't really countdown as the user has to refresh the page for it to recount. You can see it "counting" when the user is scrolling up and down cells on a UITableView as the cells do refresh the view.
Another thing is that I have on NSTimeZone of the currentDate "GMT+2:00" as it works for my time but only because I haven't figured out how to use the device NSTimeZone yet.
let releaseDate = "2015-05-02'T'22:00:00:000Z"
let futureDateFormatter = NSDateFormatter()
futureDateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
let date: NSDate = futureDateFormatter.dateFromString(releaseDate!)!
let currentDate = NSDate();
let currentFormatter = NSDateFormatter();
currentFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
currentFormatter.timeZone = NSTimeZone(abbreviation: "GMT+2:00")
let diffDateComponents = NSCalendar.currentCalendar().components([NSCalendarUnit.Month, NSCalendarUnit.Day, NSCalendarUnit.Hour, NSCalendarUnit.Minute], fromDate: currentDate, toDate: date, options: NSCalendarOptions.init(rawValue: 0))
let countdown = "\(diffDateComponents.month) m: \(diffDateComponents.day) d: \(diffDateComponents.hour) h: \(diffDateComponents.minute) min"