In Swift, how to delete hours in a Date object? - swift

i need to use a dictionary of dates, and i need to delete all the information about a date except:
day
month
year
i create this static function:
let day = Date() // it's an example
print(day)
func dateSimplificator(WithDate date: Date) -> Date {
let formatterD = DateFormatter()
formatterD.dateFormat = "dd MM yyyy"
let dayString = formatterD.string(from: date)
let reFormatterD = DateFormatter()
reFormatterD.dateFormat = "dd MM yyyy"
let dayFormatted = reFormatterD.date(from: dayString)!
//print(dayFormatted)
return dayFormatted
}
print(dateSimplificator(WithDate: day))
and when i print, i obtain:
2020-09-03 10:40:25 +0000
2020-09-02 23:00:00 +0000
it isn't what i want.
I need somthing like this:
the date => 2020-09-03 10:40:25 +0000
and when i use the static function with the date, i have to obtain a new date like this :
2020-09-02 00:00:00 +0000
what should a change in my function?

First of all your method can be written without a date formatter
func dateSimplificator(with date: Date) -> Date {
return Calendar.current.startOfDay(for: date)
}
Second of all a date formatter considers the local time zone – which is clearly UTC+0100 in your case – but print shows dates in UTC. 2020-09-03 00:00:00 +0100 and 2020-09-02 23:00:00 +0000 is the same moment in time.

Related

Swift date components incorrect return of date day number

I need to obtain a date from some variable values
So I specify year, month and day and I need a Date as return
Doing the following works except for the day because it return the day input - 1
let todayDate: Date = Calendar.current.startOfDay(for: Date.from(year: 2022, month: 09, day: 05)!)
print("today date = \(todayDate)")
extension Date {
static func from(year: Int, month: Int, day: Int) -> Date? {
let calendar = Calendar(identifier: .gregorian)
var dateComponents = DateComponents()
dateComponents.year = year
dateComponents.month = month
dateComponents.day = day
return calendar.date(from: dateComponents) ?? nil
}
}
And the output is
today date = 2022-09-04 22:00:00 +0000
Date and time can be a bit tricky. The Date struct stores a point in time relative to GMT. If you print it it will show exactly that.
Solution:
Don´t use print, use a proper Dateformatter. To illustrate what I mean use this in a playground:
let date = Calendar.current.startOfDay(for: Date())
print(date)
//2022-09-03 22:00:00 +0000
// when it is 4.th of september 00:00 in my timezone (+- Daylight saving) it is this time in GMT
let formatter = DateFormatter()
formatter.dateFormat = "dd MM yyyy HH:mm:ss"
print(formatter.string(from: date))
//04 09 2022 00:00:00
// this is the time in my timezone
So the issue here is not that it has the wrong time, it is just not presented in the correct time zone.

Problem with adding month value to date in Swift

I've got a problem. I'm getting start date of current year with function below:
func startOfYear() -> Date {
var calendar = Calendar(identifier: .iso8601)
let timezone = TimeZone(secondsFromGMT: 0)!
calendar.timeZone = timezone
return calendar.dateComponents([.calendar, .year], from: self).date!
}
My goal is to iterate through this date to extract data for every single month. I use this function to add value to .month to get start date of every month of year:
func getNextMonths(using calendar: Calendar = .iso8601, monthAmount: Int) -> Date {
calendar.date(byAdding: .month, value: monthAmount, to: self.startOfYear())!
}
When I iterate through this fuction and print dates I receive this:
func getMonth() {
for number in 0...12 {
print("month \(number): \(Date().getNextMonths(monthAmount: number))")
}
}
output:
month 0: 2022-01-01 00:00:00 +0000
month 1: 2022-02-01 00:00:00 +0000
month 2: 2022-03-01 00:00:00 +0000
month 3: 2022-03-31 23:00:00 +0000
month 4: 2022-04-30 23:00:00 +0000
month 5: 2022-05-31 23:00:00 +0000
month 6: 2022-06-30 23:00:00 +0000
month 7: 2022-07-31 23:00:00 +0000
month 8: 2022-08-31 23:00:00 +0000
month 9: 2022-09-30 23:00:00 +0000
month 10: 2022-11-01 00:00:00 +0000
month 11: 2022-12-01 00:00:00 +0000
month 12: 2023-01-01 00:00:00 +0000
As you can see there is a problem starting with 2022-03-31 - it supposed to return 2022-04-01 but I don't really know what I'm doing wrong and why I can't achieve this.
EDIT
I've changed fuction getNextMonths to check if it's daylight saving time and it's working now, thanks to [Joakim Danielson][1] for help.
It's silly solution but it works:
func getNextMonths(using calendar: Calendar = .iso8601, monthAmount: Int) -> Date {
if monthAmount == 0 || monthAmount == 1 || monthAmount == 2 || monthAmount == 10 || monthAmount == 11 || monthAmount == 12 {
return calendar.date(byAdding: .month, value: monthAmount, to: self.startOfYear())!
} else {
var dateComponents = DateComponents()
dateComponents.month = monthAmount
dateComponents.hour = 1
return calendar.date(byAdding: dateComponents, to: self.startOfYear())!
}
}
Hey I copied your code as an extension to Date and I got some errors, after some search I finally can run it and it gives me the beginning of each month, here's my changes hope it helps!
extension Date{
func startOfYear() -> Date {
var calendar = Calendar(identifier: .iso8601)
let timezone = TimeZone(secondsFromGMT: 0)!
calendar.timeZone = timezone
return calendar.dateComponents([.calendar, .year], from: self).date!
}
func getNextMonths(using calendar: Calendar, monthAmount: Int) -> Date {
calendar.date(byAdding: .month, value: monthAmount, to: self.startOfYear())!
}
func getMonth() {
for number in 0...12 {
print("month \(number): \(Date().getNextMonths(using: Calendar.current, monthAmount: number))")
}
}
}
Then I made a Date object like this
let d = Date()
print(d.getMonth())
Output (In Indian numbers, but it should be the same)

How to parse date in "2022-03-04T10:30:00-08:00" format correctly in swift?

I have date coming from API shown below. These dates are for different countries.
dateTime = "2022-03-04T14:30:00-08:00"
I need to convert this use it both as Date and as String. But I do not know if date and time I am converting are correct. I am using following code:
To Convert String from API to Date:
extension String {
var CommonDateFormat: Date? {
get {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
return dateFormatter.date(from: self)
}
}
}
To Convert Date to String:
extension Date {
func getDateAccoringTo(format: DateFormat ) -> String {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = format.rawValue
dateFormatter.timeZone = .current
dateFormatter.timeZone = TimeZone.init(identifier: "UTC")
return dateFormatter.string(from: self)
}
}
enum DateFormat: String {
case ddmmyyyy = "dd/MM/yyyy"
case mmddyyyy = "MM/dd/yyyy"
case mmmd_yyyy = "MMM d, yyyy"
case llll_yyyy = "LLLL ,yyyy"
case TIME = "HH:mm:ss"
case day = "dd"
}
When I try to get day from date it always gives next day date. For example if date = "2022-03-04T14:30:00-08:00" then if I try to get day using code below
date?.getDateAccoringTo(format: .day)
This returns 5 not 4
date?.getDateAccoringTo(format: .TIME)
This returns time 00:00:00
Am I missing something important which is leading to these values?
Also, if I am missing something in my question kindly let me know so that I can improve it.
The given string
let dateTime = "2022-03-04T14:30:00-08:00"`
is a standard ISO8601 formatted date string. It can be converted to Date with
let formatter = ISO8601DateFormatter()
let date = formatter.date(from: dateTime)!
At this specific point in time it is
14:30 on Friday, March 4 in Denver, CO, USA
22:30 on Friday, March 4 in London, UK
06:30 on Saturday, March 5 in Tokyo, Japan
Now let's see how Xcode displays dates.
print displays Date instances always in UTC indicated by +0000 which is the London time zone unless you print(date.description(with: .current), this displays the date in the local time zone.
In a Xcode Playground the result area displays Date instances in the local time zone except in print lines.
Last point to consider is that DateFormatter converts Date to String in the local time zone if no time zone is specified.
Keeping this behavior in mind you get the next day if you convert the date to string with DateFormatter but without specifying the time zone and your local time zone is greater than or equal to +01:30.
And you get the time 00:00 if you convert the date to string with DateFormatter but without specifying the time zone and your local time zone is exactly +01:30 which is a pretty unusual time zone by the way.

Calendar Not return correct .weekday swift 3.1 [duplicate]

This question already has answers here:
Swift - Weekday by current location by currentCalendar()
(2 answers)
Closed 5 years ago.
I'm trying to get weekday of given Date Object. But it always returns +1 value.
example : If I gave a date as : 2017-06-01 18:30:00 +0000
it returns weekday 6 -> Friday
It should bee weekday 5 -> Thursday
My code :
let calendar = Calendar.current
let day: Int = calendar.component(.weekday, from: self.month!)
print ("---------")
print(self.month!)
print (day)
switch day {
case 1:print("Sunday")
case 2:print("Monday")
case 3:print("Tuesday")
case 4:print("Wednesday")
case 5:print("Thursday")
case 6:print("Friday")
case 7:print("Saturday")
default:
break
}
Output on the Console : (I have given 2 dates both of them ar wrong)
---------
2016-01-01 18:30:00 +0000
7
Saturday
---------
2017-06-01 18:30:00 +0000
6
Friday
Where I did the mistake...
Thank you.
From my point of view create extension to the Date it is more clear to use:
extension Date {
func weekday() -> Int? {
return Calendar.current.dateComponents([.weekday], from: self).weekday
}
}
print(Date().weekday()!)
Example:
let dateFormatter = DateFormatter()
dateFormatter.calendar = Calendar(identifier: .gregorian)
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ssZ"
let date = dateFormatter.date(from: "2017-06-01 18:30:00 +0000")
print(date?.weekday()!) //5 In Ukraine

storing date in coredata swift

I have a textfield connected to a date picker
I am then trying to store the selected date into core data,
My log off the date picked by the user seems ok:
2016-01-29 00:00:00 +0000 [I strip the time component with some code]
This is converted into a String and displayed in the textfield called startDate.
func handleDatePicker(sender: UIDatePicker) {
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "EEE, dd MMM YYYY"
startDate.text = dateFormatter.stringFromDate(sender.date)
}
Now the strange thing is that when I try and store this into CoreData and convert the string back into a date (the attribute I am saving it into is configured as a Date)
let cont = self.context
let newCustomer = NSEntityDescription.entityForName("Customer", inManagedObjectContext: cont)
let aCust = Customer(entity: newCustomer!, insertIntoManagedObjectContext: cont)
let DF = NSDateFormatter()
DF.dateFormat = "EEE, dd MMM YYYY"
aCust.c15das = DF.dateFromString(startDate.text!)
print("Saved Date: \(DF.dateFromString(startDate.text!))")
Now the log prints out:
2015-12-25 00:00:00 +0000
Why the difference? How can I stop this happening?
Sorry if its something obvious that I am not spotting.
"EEE, dd MMM YYYY" -> YYYY: "Week of Year Calendar", aka "ISO Week Date System". The first week does not start on the first January. If the January 1st is either Monday, Tuesday, Wednesday or Thursday, the whole week is the first week of the new year. if it is Friday, Saturday or Sunday the week is the 53rd week of the last year. So this is a calendar with year that only have integral weeks. Either 52 or 53, rather than 365 or 366 days.
In this calendar January 29th would be the 5th day of the 4th week of the year 2016 — 2016-W4-5. This system does not know months and therefor your date is nonsense.
You want "EEE, dd MMM yyyy", as yyyy indicates a year that starts on 1st of January and ends after 31st of December — The Gregorian Year.
[I strip the time component with some code]
You shouldn't do that. Rather NSCalendar's method to get a date at the beginning of the day.
var today: NSDate?
cal.rangeOfUnit(.Day, startDate: &today, interval: nil, forDate: date)
Try this code, that worked for me:
let dateString = "Fri, 29 Jan 2016" // change to your date format
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "EEE, dd MMM yyyy"
dateFormatter.timeZone = NSTimeZone(name: "UTC")
let date = dateFormatter.dateFromString(dateString)
print(date!)