I want to get the week number of year associated with each date in IOS. I know I can get the ISO 8601 week number by using:
Calendar.current.component(.weekOfYear, from: Date())
But how to do it if the start day of a week could be any day of the week(like Sunday or Saturday)?
Just make your own Calendar with your own firstWeekday:
var calendar = Calendar.current
calendar.firstWeekday = someWeekdayYouLike
calendar.component(.weekOfYear, from: Date())
If you want to use the first weekday of some Locale, set the locale of the calendar instead:
var calendar = Calendar.current
calendar.locale = Locale(identifier: "en-gb")
print(calendar.firstWeekday) // 2
calendar.locale = Locale(identifier: "en-us")
print(calendar.firstWeekday) // 1
Hi i have a date in swift that i get from http call ...
Now i want to format this date like : 1st Wed April
let formatter = DateFormatter()
formatter.dateFormat = "F EEEE MMM"
let now = stats.getData()
let dateString = formatter.string(from: now)
This returns 1 Wednesday Apr but i need to formate date as 1st Wednesday Apr
To solve this we need two formatters, one for the date and one NumberFormatter for formatting 1 into 1st etc. Note that to get the order of the specific weekday in the month we use the date component .weekdayOrdinal.
The date pattern also needs to be changed to E from EEEE to show the abbreviated day name and month needs to be MMMM to show the full month name
let formatter = DateFormatter()
formatter.dateFormat = "E MMMM"
let numberFormatter = NumberFormatter()
numberFormatter.numberStyle = .ordinal
let now = stats.getData()
let day = Calendar.current.component(.weekdayOrdinal, from: now)
let ordinalDay = numberFormatter.string(from: NSNumber(value: day)) ?? String(day)
let dateString = "\(ordinalDay) \(formatter.string(from: now))"
I'm trying to print a given date in the format of "[week in a year] [year]" combination using a DateFormatter. I have given it a pattern of "w yyyy" but it returns an empty string.
let date = DateComponents(calendar: Calendar.current, year: 2018, month: 9, day: 28).date
let formatter = DateFormatter()
formatter.locale = Locale.current
formatter.setLocalizedDateFormatFromTemplate("w yyyy")
formatter.string(from: date!) // this returns ""
formatter.setLocalizedDateFormatFromTemplate("w")
formatter.string(from: date!) // this returns the correct number, like "36"
According to the Date Formatting Guide, iOS 5 uses version tr35-19. I assume that it hasn't changed since then.
In the unicode.org documentation, there is no special mention of how week of year is behaving in conjunction with a year format. What am I missing here?
EDIT I understand that I can use DateComponents to get the numbers and formatting them that way, but this question is more about why the format "w yyyy" is special.
Don't use setLocalizedDateFormatFromTemplate(). I'm not familiar with that method, but it sounds like it expects a pre-defined date string template, and your format string must not match any known templates. If you change your line
formatter.setLocalizedDateFormatFromTemplate("w yyyy")
to
formatter.dateFormat = "w yyyy"
It works as expected.
Edit:
It seems you should use:
formatter.dateFormat = "w Y"
y and yyyy will not give the correct results with certain dates.
Try this :
let date = Date()
let calendar = Calendar.current
let year = calendar.component(.year, from: date)
let month = calendar.component(.month, from: date)
let day = calendar.component(.day, from: date)
let weekOfYear = calendar.component(.weekOfYear, from: Date.init(timeIntervalSinceNow: 0))
OR
let date = Date()
let calendar = Calendar.current
let year = calendar.component(.year, from: date)
let month = calendar.component(.month, from: date)
let day = calendar.component(.day, from: date)
let weekOfYear = calendar.component(.weekOfYear, from: Date())
For my iOS App I need some calculations for Dates and Time. By using the class Calendar I found out, that this class gives me some wrong values for dates in the 19th century and before. During this time, the time zones in Europe were very unstructured. For example, GMT+0:53:28. The class Calendar knows about this and shows me the correct time zone. But the return value of "secondsFromGMT" is wrong: 3600 seconds in this case. Does anyone have some experience with this error or with related problems?
import Foundation
let timeZone = TimeZone(identifier: "Europe/Berlin")
var calendar = Calendar.current
calendar.timeZone = timeZone!
let formatter = DateFormatter()
formatter.dateFormat = "dd.MM.yyyy HH:mm:ss"
formatter.locale = Locale(identifier: "en-US")
let date = formatter.date(from: "01.07.1622 08:10:00")!
formatter.dateStyle = .long
formatter.timeStyle = .long
let stringDate = formatter.string(from: date)
let offsetFromGMT = calendar.timeZone.secondsFromGMT(for: date)
print(stringDate, " Offset =", offsetFromGMT)
July 1, 1622 at 8:10:00 AM GMT+0:53:28 Offset = 3600
I know how to get local date and time, but what I want to do is getting the date and time from different places. For example, I want to find out what the time and date is in New York. How can i solve this simple problem?
Here is my code for local date and time :
let date = NSDate()
let calendar = Calendar.current
let components = calendar.dateComponents([.hour, .minute, .month, .year, .day, .second, .weekOfMonth], from: date as Date)
let currentDate = calendar.date(from: components)
I searched about it here, but i didn't find what i want and I'm still looking for the date libaries. If you know any source or sample to redirect me, I really appreciate that.
There are several different concepts involved here, and we need to understand (almost) all of them to get this right...
1) a Date (NSDate as was, in Swift) is an absolute point in time - it's slightly mis-named, because it has nothing to do with an actual date like 13th November 2017, because to get to that we need to define ...
2) a Calendar, because 13th November 2017 in the western Gregorian calendar could also be 23rd Safar 1439 in the Islamic calendar, or the 24th of Heshvan 5778 in the Hebrew calendar, or some other things in the many other calendars that iOS & MacOS support;
3) in turn Calendar changes not only what values are returned in the DateComponents that we have to use to unpack a Date + Calendar into days, months, years & eras (e.g. BC/AD), or even week number, etc..., but also some calendars might not have the same components as others;
4) time-of-day (as you know) depends on TimeZone, so the same absolute time can be one of many different times "o'clock" depending on where you are. It may also (as you can see in the example below) change the date as well as the "o'clock". This of course could be automatic (where you are) or set by the programmer;
5) further, we have DateFormatter (which is a convenience that wraps up DateComponents), because 13th November 2017 could be represented as 13/11/17 or 11/13/17 depending on whether you are British or American. We may also wish to choose whether we use text or numeric months, and, if displaying times, whether we want 12 hour or 24 hour format - all of these are covered by DateFormatter, but text representation may be "13e Novembre 2017" if you are French, which introduces the notion of
6) Locale, which can be set, like TimeZone, as being default (as chosen when you set up the device) or specified by the programmer.
The code you posted won't work, because all it does is takes a Date, transforms it through a Calendar to DateComponents (all good so far), but then recreates a Date from the components - all you will get is the original Date - the same absolute point in time.
What I believe from the question and your answers to questions in the comments is that you want a function that takes an absolute time (eg "now") aka a Date and displays it in a specific TimeZone. This works:
func timeComponents(date: Date, timeZone: TimeZone) -> DateComponents {
var calendar = Calendar.current
calendar.timeZone = timeZone
return calendar.dateComponents([.hour, .minute, .month, .year, .day, .second, .weekOfMonth], from: date)
}
let absTime: Date = Date() // Now
let edinburgh = TimeZone(abbreviation: "GMT")!
let newYork = TimeZone(abbreviation: "EST")!
let ec = timeComponents(date: absTime, timeZone: edinburgh)
let nycc = timeComponents(date: absTime, timeZone: newYork)
print(ec)// year: 2017 month: 11 day: 14 hour: 0 minute: 44 second: 10 weekOfMonth: 3 isLeapMonth: false
print(nycc) // year: 2017 month: 11 day: 13 hour: 19 minute: 44 second: 10 weekOfMonth: 3 isLeapMonth: false
... which I think answers the minimum of your question, but to finesse it, we need to move from DateComponents to DateFormatter
func timeString(date: Date, timeZone: TimeZone, timeStyle: DateFormatter.Style) -> String {
let dateFormatter = DateFormatter()
dateFormatter.timeZone = timeZone
dateFormatter.dateStyle = .none
dateFormatter.timeStyle = timeStyle
return dateFormatter.string(from: date)
}
let es = timeString(date: absTime, timeZone: edinburgh, timeStyle: .full)
let nycs = timeString(date: absTime, timeZone: newYork, timeStyle: .full)
print(es) // 12:44:10 AM Greenwich Mean Time
print(nycs) // 7:44:10 PM Eastern Standard Time
You can go on, and start to use Locale, if you want to internationalise your app, but I'l leave that as an exercise!
p.s. These are not all of the concepts - see here
p.p.s. See also this answer and this answer (neither duplicates)
If you just want to format the date to a string, consider using a DateFormatter instead:
let date = Date()
let formatter = DateFormatter()
formatter.timeZone = TimeZone(identifier: "America/New_York")
formatter.dateStyle = .long
formatter.timeStyle = .long
formatter.string(from: date)
If you want to get the date components and process them, use the dateComponents(in:from:) method.
let components = Calendar.current.dateComponents(in: TimeZone(identifier: "America/New_York")!, from: date)
If you don't know the time zone of the place you are searching for, you can use the CoreLocation's CLGeocoder and search on an address string. Then you can get the timezone for that place and translate that into the time you're looking for:
let geocoder = CLGeocoder()
geocoder.geocodeAddressString("New York, New York") { (placemarks, error) in
guard error == nil else {
print("Error")
print(error!.localizedDescription)
return
}
guard let placemarks = placemarks,
let place = placemarks.first else {
print("No results")
return
}
if let timeZone = place.timeZone {
print("TimeZone: \(timeZone.identifier)")
// TimeZone: America/New_York
//Ignore the time zone offset from this one, it will be the difference between the current time and the new york time
let dateInNewYork = Date().addingTimeInterval(TimeInterval.init(timeZone.secondsFromGMT()))
print(dateInNewYork)
// 2017-11-13 15:03:05 +0000
//Or
let formatter = DateFormatter()
formatter.timeZone = TimeZone(identifier: timeZone.identifier)
formatter.dateStyle = .long
formatter.timeStyle = .long
let formattedDateInNewYork = formatter.string(from: Date())
print(formattedDateInNewYork)
// November 13, 2017 at 3:03:05 PM EST
//Or
let components = Calendar.current.dateComponents(in: TimeZone(identifier: timeZone.identifier)!, from: Date())
print(components.date!)
// 2017-11-13 20:03:05 +0000
}
}