Convert string time into date swift - swift

I have json from rest API :
{
"status": "ok",
"query": {
"format": "json",
"kota": "703",
"tanggal": "2017-02-07"
},
"jadwal": {
"status": "ok",
"data": {
"ashar": "15:26",
"dhuha": "06:21",
"dzuhur": "12:10",
"imsak": "04:28",
"isya": "19:31",
"maghrib": "18:20",
"subuh": "04:38",
"tanggal": "Selasa, 07 Feb 2017",
"terbit": "05:54"
}
}
}
I want convert jadwal -> data -> ashar and other into Date format
I have this code,
extension String {
func convertToDate() -> Date? {
let arr = self.split(separator: ":")
guard
let hour = Int(arr.first ?? ""),
let minute = Int(arr.last ?? "")
else { return nil }
let component = DateComponents(hour: hour, minute: minute)
var cal = Calendar.current
guard let timezone = TimeZone(identifier: "Asia/Jakarta") else { return nil }
cal.timeZone = timezone
let date = cal.date(from: component)
return date
}
}
But i get this result on my console debug
ashar: 0001-01-01 08:27:48 +0000
i expect for example on asr/ashar = 2021-01-12 15:26:00 for Indonesia Time, do you guys have advice or something?

You can create an extension for string that returns a full date object by passing only the time string as follows.
extension String {
func createDateObjectWithTime(format: String = "HH:mm") -> Date? {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = format
guard let dateObjectWithTime = dateFormatter.date(from: self) else { return nil }
let gregorian = Calendar(identifier: .gregorian)
let now = Date()
let components: Set<Calendar.Component> = [.year, .month, .day, .hour, .minute, .second]
var dateComponents = gregorian.dateComponents(components, from: now)
let calendar = Calendar.current
dateComponents.hour = calendar.component(.hour, from: dateObjectWithTime)
dateComponents.minute = calendar.component(.minute, from: dateObjectWithTime)
dateComponents.second = 0
return gregorian.date(from: dateComponents)
}
}
You can call the extension by:
let date = "15:26".createDateObjectWithTime()

Just get the current date and set hour and minute to the extracted values
extension String {
func convertToDate() -> Date? {
let arr = self.split(separator: ":")
guard
let hour = Int(arr.first ?? ""),
let minute = Int(arr.last ?? "")
else { return nil }
var cal = Calendar.current
guard let timezone = TimeZone(identifier: "Asia/Jakarta") else { return nil }
cal.timeZone = timezone
return cal.date(bySettingHour: hour, minute: minute, second: 0, of: Date())
}
}

Related

local notification with repeats

I am making a local notification that will run every year, the problem is that I need notifications that come based on the Hebrew calendar, that is, July 20, 2020 according to the Hebrew calendar 28 tamuz 5780 and if we add the year to 28 tamuz 5781 then according to the Gregorian calendar comes out on July 1, 2021, that is, according to the Gregorian calendar, the date changes, I also need to take into account the leap year, AnniversariesReminderService is responsible for the notification, thanks
July 20, 2020 is 28 tamuz 5780
but
28 tamuz 5781 is July 1, 2021
I need to automatically calculate this time difference so that every year I receive a notification according to the Jewish date
struct ReminderAnniversaries {
var id:Int!
var description:String!
var date:Date!
}
class AnniversariesReminderService {
fileprivate var formatter :DateFormatter {
let dateformatterDay = DateFormatter()
dateformatterDay.dateFormat = "yyyy.MM.dd HH:mm"
return dateformatterDay
}
func scheduleReminder(data: ReminderAnniversaries, complited: (() -> Void)? = nil) {
removeScheduledReminder(data: data)
let request = self.prepareNotificationRequest(data: data)
UNUserNotificationCenter.current().add(request, withCompletionHandler: { error in
if error != nil {
print("ERROR SCHEDULE NOTIFICATION TYPE: \(String(describing: "\(data.id!)")), ERROR: \(String(describing:error?.localizedDescription))")
}
complited?()
})
}
fileprivate func prepareNotificationRequest(data: ReminderAnniversaries) -> UNNotificationRequest {
let content = UNMutableNotificationContent()
content.sound = .default
content.title = "AppDisplayName".localized()
content.body = data.description
let fireDate = data.date!
var dateInfo = DateComponents()
let triggerDaily = Calendar(identifier: .hebrew).dateComponents([.year, .month, .day, .hour, .second], from: fireDate)
dateInfo.year = fireDate.year
dateInfo.month = fireDate.month
dateInfo.day = fireDate.day
dateInfo.hour = fireDate.hour
dateInfo.minute = fireDate.minute + 1
dateInfo.second = fireDate.second
content.userInfo = ["id": data.id, "date" : fireDate,
"description": data.description]
let trigger = UNCalendarNotificationTrigger(dateMatching: triggerDaily, repeats: true)
let requestIdentifier = "\(data.id!)"
let request = UNNotificationRequest(identifier: requestIdentifier,
content: content, trigger: trigger)
print("NOTIFICATION SCHEDULED: (String(describing: requestIdentifier))")
print("NOTIFICATION TITLE: \(String(describing: content.body))")
print("NOTIFICATION TIME: \(String(describing: self.formatter.string(from: fireDate)))")
return request
}
func removeScheduledReminder(data: ReminderAnniversaries) {
UNUserNotificationCenter.current().removePendingNotificationRequests(withIdentifiers: ["\(data.id!)"])
print("NOTIFICATION REMOVED: \(String(describing: "\(data.id!)"))")
}
func getScheduledReminderDate(data: ReminderAnniversaries) -> String? {
var scheduledDate: Date?
let semaphore = DispatchSemaphore(value: 0)
UNUserNotificationCenter.current().getPendingNotificationRequests { notifications in
notifications.forEach({ notification in
if let scheduledType = notification.content.userInfo["id"] as? Int, scheduledType == data.id {
scheduledDate = notification.content.userInfo["date"] as? Date ?? Date()
// continue;
semaphore.signal()
}
})
if scheduledDate == nil {
semaphore.signal()
}
}
semaphore.wait()
return scheduledDate != nil ? formatter.string(from: scheduledDate!) : nil
}
}
Setting of date
#objc func doneDatePicker(){
if isAlarmClock && stage != 1 {
datePicker.datePickerMode = .dateAndTime
pickerDone.setTitle("Done".localized(), for: .normal)
pickerCancel.setTitle("Back".localized(), for: .normal)
stage = 1
formatter.dateFormat = "dd-MMM-yyyy HH:mm"
} else if !isAlarmClock {
//1
formatter.dateFormat = "dd-MMM-yyyy"
formatter.calendar = Calendar(identifier: .gregorian)
let dateOfDied = formatter.string(from: datePicker.date)
selectedDate = datePicker.date
// result Jule 21 2020 г.
//2
formatter.calendar = Calendar(identifier: .hebrew) //convert to jewish date
formatter.dateFormat = "dd-MMM-yyyy"
jewishDatePicker.date = datePicker.date
jewishDatePicker.calendar = NSCalendar(calendarIdentifier: NSCalendar.Identifier.hebrew)! as Calendar //convert to jewish calendar for adding year
//count of years between date of died and current date
let calendar = Calendar.current
// Replace the hour (time) of both dates with 00:00
let date1 = calendar.startOfDay(for: selectedDate)
let date2 = calendar.startOfDay(for: Date())
let components = calendar.dateComponents([.year], from: date1, to: date2)
var dayComponent = DateComponents()
dayComponent.year = components.year! + 1
let new_date = jewishDatePicker.calendar.date(byAdding: dayComponent, to: jewishDatePicker.date) // adding year by jewish calendar
jewishSelectedDate = new_date!
let hebDate = formatter.string(from: jewishSelectedDate)
jewishDatePicker.locale = Locale(identifier: "he")
jewishDatePicker.setDate(new_date!, animated: false)
print(jewishDatePicker.date)
// result Jule 9 2021 г.
//3
formatter.calendar = Calendar(identifier: .gregorian) //convert to gregorian date
let gregDate = formatter.string(from: new_date!)
// result Jule 09 2021 г.
alarmClock.isEnabled = true
alarmClockBtn()
var txt = Localized("You choosed", arguments: "\(dateOfDied)")
txt = txt + " " + "Jewish anniversary falls on".localized() + " " + "\(gregDate) (\(hebDate))," + " " + "select the date and time to remind you".localized()
text.text = txt
} else {
reminderTime = datePicker.date
pickerView.isHidden = true
}
}
#objc func addNotificationBtn(){
if !(name.text?.isEmpty ?? false) && !(parentName.text?.isEmpty ?? false) &&
jewishSelectedDate != nil && reminderTime != nil {
errorNotifier.notify("Done".localized(), title: "Notification configured".localized(), showOK: true) { [weak self] in
let remind = ReminderService()
var txt = Localized("You have set an anniversary reminder", arguments: self!.name.text!)
txt = txt + " " + "Бен(Бат)".localized() + " " + self!.parentName.text!
let data = ReminderAnniversaries(id: 11, description: txt, date: self?.reminderTime)
remind.anniversaries.scheduleReminder(data: data) {
print("ready")
}
self?.dismiss(animated: true, completion: nil)
}
} else if (name.text?.isEmpty ?? false) && (parentName.text?.isEmpty ?? false) {
errorNotifier.notify("Check the fields".localized(), title: "Fields must not be empty".localized(), showOK: true)
} else if jewishSelectedDate == nil {
errorNotifier.notify("Please select date if died".localized(), title:"", showOK: true)
} else if reminderTime == nil {
errorNotifier.notify("Please select a time for the anniversary reminder, the time is automatically set the day before the death anniversary".localized(), title: "Please select a time reminder".localized(), showOK: true)
}
}

Can't get the necessary date

I am trying to get the difference between dates in days. I have a problem translating dates to the desired format.
func daysBefore(_ date: String) -> Int {
let currentDate = Date()
let dateFormater = DateFormatter()
dateFormater.dateFormat = "dd.mm.YYYY"
guard let nextDate = dateFormater.date(from: date) else {
return 0
}
return currentDate.interval(ofComponent: .day, fromDate: nextDate)
}
extension Date {
func interval(ofComponent comp: Calendar.Component, fromDate date: Date) -> Int {
let currentCalendar = Calendar.current
guard let start = currentCalendar.ordinality(of: comp, in: .era, for: date) else { return 0 }
guard let end = currentCalendar.ordinality(of: comp, in: .era, for: self) else { return 0 }
return end - start
}
}
daysBefore("22.09.2019")
When I convert the date from String to Date in:
let currentDate = Date()
let dateFormater = DateFormatter()
dateFormater.dateFormat = "dd.mm.YYYY"
guard let nextDate = dateFormater.date(from: date) else {
return 0
}
I always get something like: 2018-12-22 21:09:00 +0000.
But expected(in example): 22.09.2019.

How to hide next day with FSCalendar based on week

Hi I want to hide the next business day, if user registration date and current date both are same. I need to hide next working day.
Sunday and Saturday are holidays.
I write code following if user is register on Friday I need to hide Monday, how to resolve this problem.
I write like this how to hide businessday
func calendar(_ calendar: FSCalendar, shouldSelect date: Date, at monthPosition: FSCalendarMonthPosition) -> Bool {
let joingdate = "2019-01-30" //modeldata.joindate
let currentdate = date.toString(dateFormat: "yyyy-MM-dd")
let currentDate = date
let currentdayweek = date.toString(dateFormat: "EEEE")
if joingdate == currentdate
{
if currentdayweek == "Friday"{
let businessday = Calendar.current.date(byAdding: .day, value: 3, to: currentDate)
return false
}
else if currentdayweek == "Saturday"{
let businessday = Calendar.current.date(byAdding: .day, value: 2, to: currentDate)
return false
}
else if currentdayweek == "Sunday"{
let businessday = Calendar.current.date(byAdding: .day, value: 1, to: currentDate)
return false
}
else
{
let businessday = Calendar.current.date(byAdding: .day, value: 1, to: currentDate)
return false
}
}
}
func minimumDate(for calendar: FSCalendar) -> Date {
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
let myString = formatter.string(from: Date())
let yourDate = formatter.date(from: myString)
formatter.dateFormat = "yyyy-MM-dd"
let strCurrentDate = formatter.string(from: yourDate!)
var addDay = 0
if let model = modeldata{
if let joiningdate = "2019-01-31"
{
if strCurrentDate == joiningdate
{
addDay = 2
}
let currentdayweek = yourDate!.toString(dateFormat: "EEEE")
if currentdayweek == "Friday"{
addDay = 4
}
else if currentdayweek == "Saturday"{
addDay = 3
}
else if currentdayweek == "Sunday"{
addDay = 2
}
}
}
let tomorrow = Calendar.current.date(byAdding:
.day, // updated this params to add hours
value: addDay,
to: formatter.date(from: strCurrentDate)!)
return tomorrow!
}
}

How to get day and month from Date type - swift 4

I have variable with data type Date, where I have stored date in this format
2018-12-24 18:00:00 UTC
How can I get from this day or month?
Details
Xcode Version 11.0 (11A420a), Swift 5
Links
How to convert string to Date
Solution
extension Date {
func get(_ components: Calendar.Component..., calendar: Calendar = Calendar.current) -> DateComponents {
return calendar.dateComponents(Set(components), from: self)
}
func get(_ component: Calendar.Component, calendar: Calendar = Calendar.current) -> Int {
return calendar.component(component, from: self)
}
}
Usage
let date = Date()
// MARK: Way 1
let components = date.get(.day, .month, .year)
if let day = components.day, let month = components.month, let year = components.year {
print("day: \(day), month: \(month), year: \(year)")
}
// MARK: Way 2
print("day: \(date.get(.day)), month: \(date.get(.month)), year: \(date.get(.year))")
Is that String or Date type?
if it is date you can do so:
let calendarDate = Calendar.current.dateComponents([.day, .year, .month], from: date)
that will give you the day, year and month
If you saved "2018-12-24 18:00:00 UTC" as a String, you can try this:
let dateString = "2018-12-24 18:00:00 UTC"
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss 'UTC'"
guard let date = formatter.date(from: dateString) else {
return
}
formatter.dateFormat = "yyyy"
let year = formatter.string(from: date)
formatter.dateFormat = "MM"
let month = formatter.string(from: date)
formatter.dateFormat = "dd"
let day = formatter.string(from: date)
print(year, month, day) // 2018 12 24
Best Wishes!
The date string is not ISO8601 compliant, nevertheless you can use ISO8601DateFormatter if you replace <space> + UTC with Z and use custom format options.
Create a Date from the string and get the DateComponents for day and month
let string = "2018-12-24 18:00:00 UTC"
let formatter = ISO8601DateFormatter()
let trimmedString = string.replacingOccurrences(of: "\\s?UTC", with: "Z", options: .regularExpression)
formatter.formatOptions = [.withFullDate, .withFullTime, .withSpaceBetweenDateAndTime]
if let date = formatter.date(from: trimmedString) {
let components = Calendar.current.dateComponents([.day, .month], from: date)
let day = components.day!
let month = components.month!
print(day, month)
}
This is how I did in swift 4. I have a Billing class with "billDate" a field that contains the date.
extension Billing:Identifiable{
func month() -> String {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MMM"
if let inputDate = billDate {
let month = dateFormatter.string(from: inputDate)
return month.uppercased()
}
return ""
}
Extention Date All Time RETURN String:
extension Date {
func dateDistance(_ startDate: Date = Date()) -> String {
var remainingTime = ""
let dateValue = Calendar.current.dateComponents([.year,.month,.weekOfMonth,.day,.hour,.minute,.second], from: startDate, to: self)
remainingTime = String(format: "%2d Y - %2d M - %2d W - %2d D\n%02d:%02d:%02d",
dateValue.year ?? 0,
dateValue.month ?? 0,
dateValue.weekOfMonth ?? 0,
dateValue.day ?? 0,
dateValue.hour ?? 0,
dateValue.minute ?? 0,
dateValue.second ?? 0
)
return remainingTime
}
}
extension Date {
func getRemainingDayMonthYear (_ startDate: Date = Date()) -> String
{
var remainingTime = ""
let dateValue = Calendar.current.dateComponents([.year,.month,.weekOfMonth,.day,.hour,.minute,.second], from: startDate, to: self)
if dateValue.year ?? 0 > 0 {
remainingTime = dateValue.year ?? 0 > 1 ? String(format: "%2d Years",dateValue.year ?? 0) : String(format: "%2d Year",dateValue.year ?? 0)
} else if dateValue.month ?? 0 > 0 {
remainingTime = dateValue.month ?? 0 > 1 ? String(format: "%2d Months",dateValue.month ?? 0) : String(format: "%2d Month",dateValue.month ?? 0)
} else {enter code here
remainingTime = dateValue.day ?? 0 > 1 ? String(format: "%2d Days",dateValue.day ?? 0) : String(format: "%2d Day",dateValue.day ?? 0)
}
return remainingTime
}
}
If you have a date variable you can also use this solution for SwiftUi:
let date = Date()
Text(date, style: .time) // January 8, 2023
Text(date, style: .date) // 12:08 PM

Get the first day of a month in swift

I'm looking for a way to get the first day of a month (in Swift).
I would like to know if it is a Monday, Tuesday etc... by returning the number corresponding.
I try many solution like getting a NSCalendar component .weekDay but no one work.
Example :
print(getTheFirstDate("2016-2-18"))
// Should return : 0 (because the first day of February 2016 is Monday).
Any help would be appreciate.
First you need to parse your date string, then you can use Calendar method dateComponents to get the calendar, year and month components from that date and create a new date from those components. Then you can extract the weekday date component from it:
Xcode 11.5 • Swift 5.2
extension Date {
var weekday: Int { Calendar.current.component(.weekday, from: self) }
var firstDayOfTheMonth: Date {
Calendar.current.dateComponents([.calendar, .year,.month], from: self).date!
}
}
extension String {
static var dateFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd"
return formatter
}()
var date: Date? {
String.dateFormatter.date(from: self)
}
}
"2016-2-18".date?.firstDayOfTheMonth.weekday // 2 = Monday (Sunday-Saturday 1-7)
extension Date {
var startOfWeek: Date {
let gregorian = Calendar(identifier: .gregorian)
let sunday = gregorian.date(from: gregorian.dateComponents([.yearForWeekOfYear, .weekOfYear], from: self))
return gregorian.date(byAdding: .day, value: 1, to: sunday!)!
}
var endOfWeek: Date {
let gregorian = Calendar(identifier: .gregorian)
let sunday = gregorian.date(from: gregorian.dateComponents([.yearForWeekOfYear, .weekOfYear], from: self))
return gregorian.date(byAdding: .day, value: 7, to: sunday!)!
}
var startOfPreviousWeek: Date {
let gregorian = Calendar(identifier: .gregorian)
let sunday = gregorian.date(from: gregorian.dateComponents([.yearForWeekOfYear, .weekOfYear], from: self))
return gregorian.date(byAdding: .day, value: -6, to: sunday!)!
}
var endOfPreviousWeek: Date {
let gregorian = Calendar(identifier: .gregorian)
let sunday = gregorian.date(from: gregorian.dateComponents([.yearForWeekOfYear, .weekOfYear], from: self))
return gregorian.date(byAdding: .day, value: 0, to: sunday!)!
}
var startDateOfMonth: Date {
return Calendar.current.date(from: Calendar.current.dateComponents([.year, .month], from: Calendar.current.startOfDay(for: self)))!
}
var endDateOfMonth: Date {
return Calendar.current.date(byAdding: DateComponents(month: 1, day: -1), to: self.startDateOfMonth)!
}
var getPreviousMonthDate: Date {
return Calendar.current.date(byAdding: .month, value: -1, to: self)!
}
var startDateOfPreviousMonth: Date {
return getPreviousMonthDate.startDateOfMonth
}
var endOfPreviousMonth: Date {
return getPreviousMonthDate.endDateOfMonth
}
}
Well to get the corresponding number of the day of the week you can use:
var weekday = calendar!.component(NSCalendarUnit.Weekday, fromDate: yourNSDate)
var weekdayName = self.getDayOfWeek(weekday)
Then you can call this function I created to get the corresponding name of the day of the week based on the number passed in to getDayOfWeek()
func getDayOfWeek(weekday:Int) -> String {
if(weekday == 1) {
return "Sunday"
}
else if(weekday == 2) {
return "Monday"
}
else if(weekday == 3) {
return "Tuesday"
}
else if(weekday == 4) {
return "Wednesday"
}
else if(weekday == 5) {
return "Thursday"
}
else if(weekday == 6) {
return "Friday"
}
else {
return "Saturday"
}
}
And if you are using a String as a date to begin with you can change it into an NSDate like this:
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = /*place date format here*/
let date = dateFormatter.dateFromString(/*your_date_string*/)
I like Leo's answer, but in case you want to encapsulate the logic into a single function or don't want to use extensions.
func getDayOfWeekForFirstDayOfMonthFromDateString(dateString:String) -> String? {
let formatter = NSDateFormatter()
formatter.dateFormat = "yyyy-MM-dd"
if let date = formatter.dateFromString(dateString) {
if let firstOfMonth = NSCalendar.currentCalendar().dateFromComponents(NSCalendar.currentCalendar().components([.Year, .Month], fromDate: date)) {
formatter.dateFormat = "EEEE"
return formatter.stringFromDate(firstOfMonth)
}
}
return nil
}
EDIT: Adjusted code to utilize Leo's great suggestion, and borrowed his more terse creation of the creation of the first of the month object. Thanks, Leo!