How to change timezone of DatePicker in SwiftUI - ios

I'm trying to make an mobile app for a reservation system. Users can reserve the product from different timezones. So when a user from NY city tries to reserve a product from Paris, I need to be sure user selected the time in Europe/Paris timezone. Currently swiftUI datepicker uses the system current timezone which is of course GMT-5 so when they select 13:00 the Date() object sets itself to 18:00 UTC, but I need him/her to be select in GMT+1 so when they select 13:00 I should set the Date() object to 12:00 UTC. I have tried to use environment value for timezone but it changes the timezone application wide, I just need to change the timezone of datepicker not all application.
Here are the solutions I've tried to change timezone
DatePicker("", selection: $viewModel.tripRequest.date, displayedComponents: .hourAndMinute)
.labelsHidden()
.padding(.horizontal)
.font(.custom("Gilroy-Regular", size: 36))
.cornerRadius(15)
.environment(\.timeZone, TimeZone(secondsFromGMT: 3600)!)
I've also tried to use introspect with no luck
DatePicker("", selection: $viewModel.tripRequest.date, displayedComponents: .hourAndMinute)
.labelsHidden()
.padding(.horizontal)
.font(.custom("Gilroy-Regular", size: 36))
.cornerRadius(15)
.introspectDatePicker { datePicker in
datePicker.timeZone = TimeZone(secondsFromGMT: 3600)
}

SwiftUI's DatePicker uses the device's Timezone by default.
You can specify a Timezone using .environment(\.timeZone, TimeZone(identifier: "Specific identifier")!)
But Date is in UTC so if the user picks a date in one timezone when viewed in another timezone it will be adjusted. You can't change the timezone for Date.
import SwiftUI
struct WorldTimeView: View {
#State private var date: Date = .init()
var body: some View {
VStack{
DatePicker("US", selection: $date, displayedComponents: .hourAndMinute)
//US Date Picker
.environment(\.timeZone, TimeZone(identifier: "America/New_York")!)
DatePicker("Paris", selection: $date, displayedComponents: .hourAndMinute)
//Paris Date Picker
.environment(\.timeZone, TimeZone(abbreviation: "CET")!)
//User/Device Date Picker
DatePicker("Local", selection: $date, displayedComponents: .hourAndMinute)
}
}
}
struct WorldTimeView_Previews: PreviewProvider {
static var previews: some View {
WorldTimeView()
}
}

Related

How to check if date picker is opened or closed in view SwiftUI. without Tap Gesture on Date picker

When the user hits date picker in swiftUI, it opens up and shows calendar to choose date user may or may not choose date and user hits somewhere else in the view and date picker closes it self. I want to change date picker parent view border when user hits date picker and also when user tap somewhere else screen date picker closes and its parent view border does not changes.I want to handle the date picker parent view border color. when then date picker is closed or dismissed.
DatePicker("", selection: $datePicker, displayedComponents: .date)
.labelsHidden()
.padding(.trailing, 8)
.frame(alignment: .leading)
.colorMultiply(AppColors.textNavy100Color)
.accentColor(AppColors.textNavy100Color)
.onTapGesture {
print("date picker tapped")
if isFieldEditing == false{
isFieldEditing = true
}else {
isFieldEditing = false
}
}

SwiftUI DatePicker not selecting in sheet

Im using the native DatePicker in swiftUI presented through a sheet. The date picker it self is of graphical style. When the sheet is presented I can scroll through months but I cannot make a selection. To make a selection I have to constantly press on the date for 5-6 seconds. But if I use a wheel style everything works as expected. Im not sure if this is an iOS bug or something I am missing. Note: code works on preview_provider but not on actual device.
#State var showCalendar:Bool = false
#State var selectedDate:Date = Date()
.sheet(isPresented: $showCalendar){
VStack{
DatePicker("", selection: $selectedDate, displayedComponents: [.date])
.datePickerStyle(.graphical)
Spacer()
}
}

How do I set a datePicker's display to an AppStorage time (hour, min) settings?

I'm trying to allow the user to select what time they want a notification to go off through time selection on a datePicker. I have a datePicker set to only display the time as follows:
DatePicker("First Workout Notification Time", selection: $firstNotificationTime, displayedComponents: .hourAndMinute)
I want the firstNotificationTime #State var to use my #AppStorage time vars which are set as defaults on this page above the "var body: some View" as:
#AppStorage("startNoficationHour") var startNoficationHour: Int = 9
#AppStorage("startNoficationMin") var startNoficationMin: Int = 30
When the view loads (i.e. .onAppear(){}) I want the datePicker's $firstNotificationTime to get set to the startNoficationHour and startNoficationMin
my view is set up as follows:
var body: some View {
VStack {
DatePicker("First Workout Notification Time", selection: $firstNotificationTime, displayedComponents: .hourAndMinute)
}
}
.onAppear(){
// set datePicker's fisrtNotificationTime to startNotificationHour and startNotificationMin
let components = DateComponents(calendar: Calendar.current, timeZone: TimeZone.current, hour:startNoficationHour, minute: startNoficationMin)
firstNotificationTime = components.date!
print("start hour is \(startNoficationHour) and start minute is \(startNoficationMin)")
}
.onDisappear(){
// sets startNotificationHour and startNotificationMin to datePicker
let components = Calendar.current.dateComponents([.hour, .minute], from: firstNotificationTime)
startNoficationHour = components.hour!
startNoficationMin = components.minute!
print("start hour is set to \(startNoficationHour) and start minute is set to \(startNoficationMin)")
}
ok so all I had to do was set a component variable to the hour and minute and place that in the onAppear
let components = DateComponents(calendar: Calendar.current, timeZone: TimeZone.current, hour:startNoficationHour, minute: startNoficationMin)
firstNotificationTime = components.date!
I updated my question above with the answer which was based on the comment from Tushar Sharma above that linked to this Set default date on DatePicker in SwiftUI?
You are doing so much thing. There is easy solution. Use a shadow property.
Date has a method that convert the time into a double value. So, you can store the double value into #AppStorage and use it to update the date.
Here is an example,
Create a #State date variable,
#State var reminderTime = Date()
Create a show property save the date.
#AppStorage("reminderTime") var reminderTimeShadow: Double = 0
Now in the DatePicker,
DatePicker("", selection: Binding(
get: {reminderTime}, set: {
reminderTimeShadow = $0.timeIntervalSince1970
reminderTime = $0
setNotification()
}), displayedComponents: .hourAndMinute)
.onAppear {
reminderTime = Date(timeIntervalSince1970: reminderTimeShadow)
}
Here, you use the explicit binding to get and set the value and when setting the value of reminderTime, you also set the value reminderTimeShadow and save it by #AppStorage and use this in .onAppear by using reminderTime = Date(timeIntervalSince1970: reminderTimeShadow) thus update reminderTime and the view.

SwiftUI Datepicker changes format after selecting date

I've implemented a DatePicker with SwiftUI.
It works for the most part as is should, but when selecting a specific date, e.g 26. Nov 2019, it changes the format of the displayed date text.
Exampels:
Expected: 26. Nov 2019
Got: 26.11.2019
Expected 27. Nov 2019
Got: 27. Nov 2019
I have tried using the environment with a specific locale but it did not fix it.
Building my own DatePicker works, but it's not what I want.
The DatePicker also print this in the console:
UIDatePicker is being laid out below its minimum width of 280. This may not look like expected, especially with larger than normal font sizes.
This is my SwiftUI code:
private struct GeneralSection: View {
#ObservedObject var viewController: SettingsViewController
var body: some View {
Section(header: Text("General")) {
TextField("Name", text: $viewController.coupleName)
DatePicker(LocalizedStringKey("Date"),
selection: $viewController.coupleDate,
in: ...Date(),
displayedComponents: .date)
}
}
}
Gif from this problem

SwiftUI DatePicker should be editable inline

I'm using a DatePickerinside a SwiftUI List. I'm only interested in hours and minutes and therefore don't need the newly introduced calendar view.
How can I prevent the popup that appears once a user taps on the time (8:30 AM)? It would be ideal if it can be edited inline like in the iOS calendar app.
Here's how I'm creating the DatePicker:
DatePicker("Send motivation at", selection: $settings.dailyMotivationReminder, displayedComponents: .hourAndMinute)
.datePickerStyle(DefaultDatePickerStyle())
.font(.system(.body, design: .serif))
.disabled(!settings.isDailyMotivationEnabled)
.opacity(settings.isDailyMotivationEnabled ? 1.0 : 0.4)
You can use GraphicalDatePickerStyle:
List {
HStack {
Text("Send motivation at")
DatePicker("", selection: $settings.dailyMotivationReminder, displayedComponents: .hourAndMinute)
.datePickerStyle(GraphicalDatePickerStyle())
.font(.system(.body, design: .serif))
}
}

Resources