minimumDate equivalent in swiftUI? - datepicker

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

Related

How do I implement the date range for a custom DatePicker in Swift 5

I am building an iOS/iPhone application using Swift 5 / Xcode 14.1. I've created and can display a DatePicker. However, any range I provide, using the in: parameter is ignored. How do I correctly set the range.
I've constructed a view with a DatePicker as so:
DatePicker(
"Please enter the start time",
selection: $startTime,
in: ...Date()
) .labelsHidden()
.datePickerStyle( WheelDatePickerStyle() )
I am expecting to see a date picker that would allow a date up to the current date and time but instead I see this:
a datepicker
#State var selectedDate = Date()
var dateClosedRange: ClosedRange<Date> {
let min = Calendar.current.date(byAdding: .day, value: -1, to: Date())!
let max = Calendar.current.date(byAdding: .day, value: 1, to: Date())!
return min...max
}
DatePicker(
selection: $selectedDate,
in: dateClosedRange,
displayedComponents: [.hourAndMinute, .date],
label: { Text("Due Date") }
)
This example is working perfectly bro
DatePicker(
"", selection: $profile.goalDate,
in: Calendar.current.date(byAdding: .month, value: -1, to: profile.goalDate)! ... Calendar.current.date(byAdding: .month, value: 1, to: profile.goalDate)!,
displayedComponents: .date
)
.datePickerStyle( WheelDatePickerStyle() )
Wheel stop scrolling and again re position itself to date range

How to Omit Missing Fields from Date String (day, month, year)?

I have a DateFormatter where dateStyle is set to .long like so:
private let formatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateStyle = .long
return formatter
}()
In my application, I make requests to an API and can receive some info about dates in the response body. In response, it'll look like this for example:
struct StartDate {
let day: Int?
let month: Int?
let year: Int?
}
As all the fields are optional, some fields may or may not be present. For example, I may have a year and month, but not a day. Or maybe I only have the year. A demonstration of why this is a problem:
let date = Calendar.current.date(from: DateComponents(year: 2020, month: 12))!
print(formatter.string(from: date))
We have the year and month, but not the day. I may expect it to look like December 2020, December, 2020 or even December ?, 2020. However, it decides to replace the missing day with a 1. I can't use that because it's misleading to the user. How could I solve this problem?
Maybe a bit straight-forward but still. You can try something like this:
struct StartDate {
let day: Int?
let month: Int?
let year: Int?
var string: String {
get {
let daySymbols = day == nil ? "??" : String(day!)
let monthSymbols = month == nil ? "??" : DateFormatter().monthSymbols[month! - 1]
let yearSymbols = year == nil ? "??" : String(year!)
return "\(daySymbols) \(monthSymbols) \(yearSymbols)"
}
}
}
print(StartDate(day: nil, month: 10, year: 2020).string)
//prints '?? October 2020'
print(StartDate(day: 21, month: nil, year: 2020).string)
//prints '21 ?? 2020'
print(StartDate(day: 21, month: 9, year: nil).string)
//prints '21 September ??'

Swift - Check two arrays are they have same day without looping in a loop

I have 2 arrays [Date]
First is with myDates:[Date]
Second is with coreDataDates:[Date]
I'm going to for loop the second array with Core Data Dates
How to check in the loop is the DAY of myDates existing in coreDataDates ?
I know that, I can use the function NSCalendar isDate(_:inSameDayAs:), but is there a function that I don't need to loop myDates:[Date] in the coreDataDates:[Date] for loop?
Newbie example:
for date1 in coreDataDates{
for date2 in myDates{
if(Calendar.current.isDate(date1, inSameDayAs: date2)==true){
//have it
}else{
//don't have it
}
}
}
I need code that I don't have to use loop in the loop
If you don't care about time, Apple recommends that you set the time to noon because every day has a noon but not a midnight due to clock changes for daylight saving time.
Convert all dates in the two arrays to noon and then find the union of the two sets:
import Foundation
extension Date {
var noon: Date {
return Calendar.current.date(bySettingHour: 12, minute: 0, second: 0, of: self)!
}
}
let myDates = [
DateComponents(calendar: .current, year: 2018, month: 12, day: 1, hour: 1).date!,
DateComponents(calendar: .current, year: 2018, month: 12, day: 2, hour: 2).date!,
DateComponents(calendar: .current, year: 2018, month: 12, day: 4, hour: 3).date!
]
let coreDataDates = [
DateComponents(calendar: .current, year: 2018, month: 12, day: 1, hour: 4).date!,
DateComponents(calendar: .current, year: 2018, month: 12, day: 3, hour: 5).date!,
DateComponents(calendar: .current, year: 2018, month: 12, day: 4, hour: 6).date!
]
let myDateSet = Set(myDates.map { $0.noon })
let coreDataDateSet = Set(coreDataDates.map { $0.noon })
let commonDateSet = myDateSet.intersection(coreDataDateSet)
print(commonDateSet)
You can use the power of the Set class
let dateSet = Set(myDates)
let common = dateSet.intersection(coreDataDates)
//If you want it as an array
let commonDatesArray = Array(common)
See the documentation for the Set class for more info.
Something like:
let date1 = Date(timeIntervalSince1970: 1544019937)
let date2 = Date(timeIntervalSince1970: 1544019936)
let date3 = Date(timeIntervalSince1970: 1544019935)
let date4 = Date(timeIntervalSince1970: 1544019934)
let date5 = Date(timeIntervalSince1970: 1544019933)
let date6 = Date(timeIntervalSince1970: 1544019932)
let arr1 = [date1, date2, date3]
let arr2 = [date4, date5, date6]
print(arr2.filter { arr1.contains($0) }.count > 0 ) // false
let arr1 = [date1, date2, date3]
let arr2 = [date1, date5, date6]
print(arr2.filter { arr1.contains($0) }.count > 0 ) // true

How to find the nearest date of the stored data

For example:
stored data: date = data1(2015.12.31), data2(2016.01.05), data3(2016.01.14), data4(2016.01.15), data5(2016.01.18)
today is 2016.01.12
then nearest data is data3
What are the methods that can be called here data3?
realDate(datePicker.date), date(textField.text), content(textField.text) in Core Data.
var stores: Contact!
// Contact is CoreData Entity Name.
#IBOutlet weak var label: UILabel!
ViewController viewDidLoad :
let list = [stores]
let timeSort = list.map{_ in stores?.realDate!.timeIntervalSinceNow}.filter{$0 > 0}.sort(<)
if let firstTime = timeSort.first {
_ = NSDate(timeIntervalSinceReferenceDate: firstTime!)
if timeSort.first != nil {
label.text = stores?.content
} else { }
}
I was trying to get help for writing code. There is no error, it does not display any information on the label.
You can use NSDate property timeIntervalSinceNow to sort your dates and get the first positive value:
edit/update:
Swift 3 introduced Date which conforms to Comparable protocol so it can be easily sorted now:
extension Date {
init?(_ year: Int,_ month: Int,_ day: Int) {
guard let date = DateComponents(calendar: .current, year: year, month: month, day: day, hour: 12).date else { return nil }
self = date
}
}
Playground testing:
let dateList = [Date(2018, 2, 18)!, Date(2017, 12, 31)!, Date(2018, 1, 5)!, Date(2018, 2, 14)!, Date(2018, 2, 15)!]
if let closestDate = dateList.sorted().first(where: {$0.timeIntervalSinceNow > 0}) { // "Feb 15, 2018, 12:00 PM"
print(closestDate.description(with: .current)) // Thursday, February 15, 2018 at 12:00:00 PM Brasilia Summer Time
}

Testing for Anniversary Date using NSDate/NSCalendar

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)!")
}
}