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
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.
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.
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
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
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