Problem with adding month value to date in Swift - 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)

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.

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

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.

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

While a date is not within 2 dates, increase the 2 dates until the date is within. Swift

I have the following code which has a function with a selected date which is chosen by a user. This passes in a currentStart and endDate which is retrieved from CoreData and i want to create a newStartDate and newEndDate based on the previous startDate and endDate which was passed into the below function:
func calcStartAndEndDateBasedOnCurrentExsisting(selectedSpendDate: NSDate, currentStartDate: NSDate,
currentEndDate: NSDate, durationOccurance: Double) {
//initialising the newStartDate and newEndDate
var newStartDate : NSDate = currentStartDate
var newEndDate : NSDate = currentEndDate
var occurance : Int
//if the selectedSpendDate is before the currentStartDate, make the occurance a negative so it goes back in time. durationOccurance is how many days to increase/decrease by
if selectedSpendDate.earlierDate(currentStartDate).isEqualToDate(selectedSpendDate) {
occurance = -Int(durationOccurance)
}
else {
occurrence = Int(durationOccurance)
}
print("old end date = \(currentEndDate)")
components.day = occurance
while newStartDate.compare(selectedSpendDate) == .OrderedDescending || newEndDate.compare(selectedSpendDate) == .OrderedAscending {
print("\(selectedSpendDate) is not within \(newStartDate) & \(newEndDate)")
let test = newStartDate
print("old start date = \(test)")
let newDate = calendar.dateByAddingComponents(components, toDate: test, options: [])!
newStartDate = newDate
print("new StartDate = \(newStartDate)")
//working out end date from the computed start date
let calculatedEndDay = rangeOfPeriod(.Day, date: newStartDate).1
components.day = Int(durationOccurance) - 1
newEndDate = calendar.dateByAddingComponents(components, toDate: calculatedEndDay, options: [])!
print("Start: \(newStartDate) End: \(newEndDate)")
}
}
It seems to work for initially. For example when the currentStartDate is 24/03/2016, this changes successfully to the 25/03/2016 however this never changes to the 26/03/2016.
the output is shown below:
old end date = 2016-03-24 23:59:59 +0000
2016-03-26 10:20:22 +0000 is not within 2016-03-24 00:00:00 +0000 & 2016-03-24 23:59:59 +0000
old start date = 2016-03-24 00:00:00 +0000
new StartDate = 2016-03-25 00:00:00 +0000
Start: 2016-03-25 00:00:00 +0000 End: 2016-03-25 23:59:59 +0000
2016-03-26 10:20:22 +0000 is not within 2016-03-25 00:00:00 +0000 & 2016-03-25 23:59:59 +0000
old start date = 2016-03-25 00:00:00 +0000
new StartDate = 2016-03-25 00:00:00 +0000
Any help would be appreciated :)
It works as expected when components.day = occurance is within the while loop

Calculating StartDate and endDate of a day based on todays date. Swift 2

I have the following function which i am using to calculate a start and end of todays date. It was working perfectly last week, i think it may have something to do with the clocks going forwards?
func rangeOfPeriod(period: NSCalendarUnit, date: NSDate) -> (NSDate, NSDate) {
let calendar = NSCalendar.currentCalendar()
var startDate: NSDate? = nil
var duration: NSTimeInterval = 0
calendar.rangeOfUnit(period, startDate: &startDate, interval: &duration, forDate: date)
let endDate = startDate!.dateByAddingTimeInterval(duration - 1)
return (startDate!, endDate)
}
When I try and calculate the start and end of a day using:
print("Start of Day = \(rangeOfPeriod(.Day, date: NSDate()).0), End of Day = \(rangeOfPeriod(.Day, date: NSDate()).1)")
I get the following, where the start and end date is 1hour behind what is expected:
Start of Day = 2016-03-27 23:00:00 +0000, End of Day = 2016-03-28 22:59:59 +0000
when i would expect:
Start of Day = 2016-03-28 00:00:00 +0000, End of Day = 2016-03-28 23:59:59 +0000
Any help would be appreciated