I am looking for a list of timezones but when try to generate that I get the DST offset added to it. But I want the standard time, not the one with DST.
Here is the code I am using. For Denmark, I am getting GMT+2 instead of GMT+1
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .long
dateFormatter.timeStyle = .long
dateFormatter.dateFormat = "ZZZZ"
let list = TimeZone.knownTimeZoneIdentifiers
for (i, city) in list.enumerated() {
let timezone = TimeZone(identifier: city)
dateFormatter.timeZone = timezone
var isSupportDST = false
if timezone?.nextDaylightSavingTimeTransition != nil {
isSupportDST = true
}
let date = Date()
var timezoneString = dateFormatter.string(from: date)
if timezoneString.count > 3 {
timezoneString.insert(" ", at: timezoneString.index(timezoneString.startIndex, offsetBy: 3))
}
if timezoneString.count > 5 {
timezoneString.insert(" ", at: timezoneString.index(timezoneString.startIndex, offsetBy: 5))
}
var formattedCityName = city
formattedCityName = city.replacingOccurrences(of: "_", with: " ")
var dstoffset = 0 as TimeInterval
if let offset = timezone?.daylightSavingTimeOffset(){
dstoffset = offset
}
let cityWithTimezone = CityWithTimeZone(city: formattedCityName, timeZoneString: timezoneString, timeZoneInSeconds: timezone?.secondsFromGMT() ?? 0, dstOffset: dstoffset, isDSTSupport: isSupportDST)
cityList.insert(cityWithTimezone, at:i)
}
Please try to set the timezone of the formatter like this
let timezone = TimeZone(identifier: city)
dateFormatter.timeZone = TimeZone(secondsFromGMT: TimeZone.current.secondsFromGMT())
It will set the current time properly.
Related
All,
I am trying to convert UTC date to local date . Below is my code. But, even after converting I get both dates in UTC only.
static func getTodayDateInLocalTimeZone() -> Date{
let todaydateInUTC = Date()
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
dateFormatter.timeZone = TimeZone(identifier: "UTC")
let utcDateString = dateFormatter.string(from: todaydateInUTC)
print("Date::: utcDateString: \(utcDateString)")
// Changing to Current timezone
let timzoneIdentiier = TimeZone.current.identifier
let timezone = TimeZone(identifier: timzoneIdentiier)
let abbrv = timezone?.abbreviation()
let dateFormatter1 = DateFormatter()
dateFormatter1.timeZone = TimeZone(identifier: abbrv!)
dateFormatter1.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
print("Date:::timeZone: \(timzoneIdentiier) == \(String(describing: abbrv))")
let formattedDate1 = dateFormatter1.date(from: utcDateString)
print("Date:::: \(formattedDate1)")
return formattedDate1!
}
Here is what I get when I print
Date::: utcDateString: 2021-01-20T17:39:15+0000
Date:::timeZone: America/New_York == Optional("EST")
Date:::: Optional(2021-01-20 17:39:15 +0000)
Please let me know why is it now changing to the local timezone.
Thanks
First of all, a date does not have a time zone.
So let todaydateInUTC = Date() actually means let todaydate = Date().
The time zone becomes relevant, when you want to present a date to the user.
So instead of creating a new date from a the utcDateString, you just need to create another date string from the same date variable.
let formattedDate1 = dateFormatter1.date(from: utcDateString) becomes let tzDateString = dateFormatter1.string(from: todaydate).
This also means your function should return a string instead of a date.
For example:
func getTodayDateInLocalTimeZone() -> String
{
let now = Date()
// Just for debugging. Not for the result.
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
dateFormatter.timeZone = TimeZone(identifier: "UTC")
let utcDateString = dateFormatter.string(from: now)
print("Date::: utcDateString: \(utcDateString)")
let tz = TimeZone.current
let dateFormatter1 = DateFormatter()
dateFormatter1.timeZone = tz
dateFormatter1.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
print("Date:::timeZone: \(tz) == \(String(describing: tz.abbreviation()))")
let tzDateString = dateFormatter1.string(from: now)
print("Date:::: \(tzDateString)")
return tzDateString
}
For me it results in:
Date::: utcDateString: 2021-01-20T18:19:44+0000
Date:::timeZone: Europe/Berlin (current) == Optional("CET")
Date:::: 2021-01-20T19:19:44+0100
I need to return date string is same format I retrieve it, but after converting to Date and back it lose few characters
var dateStr = "2019-08-02T11:46:46.5117312Z"
let formatter = DateFormatter()
formatter.calendar = Calendar(identifier: .iso8601)
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.timeZone = TimeZone(secondsFromGMT: 0)
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ"
let date = formatter.date(from: dateStr)
var str = formatter.string(from: date!) // ===>>> "2019-08-02T11:46:46.511Z"
You can do it with custom formatter. But note that there not enough Double precision to store date. Result is 2019-08-02T11:46:46.5117311Z. Code:
class CustomDateFormatter {
private let dateFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.calendar = Calendar(identifier: .iso8601)
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.timeZone = TimeZone(secondsFromGMT: 0)
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss"
return formatter
}()
func date(fromString str: String) -> Date? {
let strs = str.components(separatedBy: CharacterSet(charactersIn: ".Z"))
if strs.count != 3 {
return nil
}
let dateStr = strs[0]
let secondsStr = strs[1]
guard let date = dateFormatter.date(from: dateStr),
let seconds = Double("0."+secondsStr) else {
return nil
}
let timeinteval = date.timeIntervalSince1970 + seconds
return Date(timeIntervalSince1970: timeinteval)
}
func string(fromDate date: Date) -> String {
let clippedDate = Date(timeIntervalSince1970: floor(date.timeIntervalSince1970))
let seconds = date.timeIntervalSince1970.truncatingRemainder(dividingBy: 1)
var lastPart = String(format: "%.7f", seconds)
lastPart = (lastPart as NSString).substring(from: 1)
return "\(dateFormatter.string(from: clippedDate))\(lastPart)Z"
}
}
let dateStr = "2019-08-02T11:46:46.5117312Z"
let formatter = CustomDateFormatter()
let date = formatter.date(fromString: dateStr)!
print(formatter.string(fromDate: date)) // =====>> 2019-08-02T11:46:46.5117311Z
I am formatting a randomly generated future date but it always returns nil even if the format of dateString is matching and has a value.
But if I try with only "(Date())" instead of newDate, it is successful.
let byDays = Int.random(in: 0...30)
var components = DateComponents()
components.day = byDays
let newDate = String(describing: Calendar.current.date(byAdding: components, to: Date()))
//give the current date output in string
let dateFormatterGet = DateFormatter()
dateFormatterGet.isLenient = true
dateFormatterGet.dateFormat = "yyyy-MM-dd HH:mm:ss Z"
dateFormatterGet.locale = Locale(identifier: "en_US_POSIX")
//describe the new format
guard let date = dateFormatterGet.date(from: newDate) else {
return ""
}
let newDateFormatter = DateFormatter()
newDateFormatter.dateFormat = "MMM dd"
let newStr = newDateFormatter.string(from: date)
print(newStr)
I want the date optional(2019-07-23 17:44:23 +0000) to be printed as Jul 23.
I don't understand the purpose of String(describing: ... You can use the date from the Calendar right away:
func randomFutureDate() -> String? {
let day = Int.random(in: 0...30)
var components = DateComponents()
components.day = day
guard let date = Calendar.current.date(byAdding: components, to: Date()) else {
return nil
}
let newDateFormatter = DateFormatter()
newDateFormatter.dateFormat = "MMM dd"
return newDateFormatter.string(from: date)
}
I want to display calendar in this format
to the user. One option is to use "string range" to get the individual calendar components. The second one is to get it using NSCalendar which to me looks like the better one (is it?). So my code is as below. But there are two problems.
I am not getting the local time form "hour & minute components"
I am getting month in Int. I want it to be in String (month in mediumStyle)
Anyone know how to get what I need? Image attached is what exactly I want to achieve. There I am using three UILabel one for "date", second for "month, year" and third for "time".
Any help would be appreciated.
var inputDateString = "Jun/12/2015 02:05 Am +05:00"
override func viewDidLoad() {
super.viewDidLoad()
let newDate = dateformatterDateString(inputDateString)
let calendar = NSCalendar.currentCalendar()
let components = calendar.components(.CalendarUnitHour | .CalendarUnitMinute | .CalendarUnitMonth | .CalendarUnitYear | .CalendarUnitDay, fromDate: newDate!)
let hour = components.hour
let minutes = components.minute
let month = components.month
let year = components.year
let day = components.day
println(newDate)
println(components)
println(day) // 12
println(month) // 6 -----> Want to have "Jun" here
println(year) // 2015
println(hour) // 2 ------> Want to have the hour in the inputString i.e. 02
println(minutes) // 35 ------> Want to have the minute in the inputString i.e. 05
}
func dateformatterDateString(dateString: String) -> NSDate? {
let dateFormatter: NSDateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "MMM/dd/yyyy hh:mm a Z"
// dateFormatter.timeZone = NSTimeZone(abbreviation: "UTC")
dateFormatter.timeZone = NSTimeZone.localTimeZone()
return dateFormatter.dateFromString(dateString)
}
You can use DateFormatter as follow:
extension Formatter {
static let monthMedium: DateFormatter = {
let formatter = DateFormatter()
formatter.dateFormat = "LLL"
return formatter
}()
static let hour12: DateFormatter = {
let formatter = DateFormatter()
formatter.dateFormat = "h"
return formatter
}()
static let minute0x: DateFormatter = {
let formatter = DateFormatter()
formatter.dateFormat = "mm"
return formatter
}()
static let amPM: DateFormatter = {
let formatter = DateFormatter()
formatter.dateFormat = "a"
return formatter
}()
}
extension Date {
var monthMedium: String { return Formatter.monthMedium.string(from: self) }
var hour12: String { return Formatter.hour12.string(from: self) }
var minute0x: String { return Formatter.minute0x.string(from: self) }
var amPM: String { return Formatter.amPM.string(from: self) }
}
let date = Date()
let dateMonth = date.monthMedium // "May"
let dateHour = date.hour12 // "1"
let dateMinute = date.minute0x // "18"
let dateAmPm = date.amPM // "PM"
NSDateFormatter has monthSymbols, shortMonthSymbols and veryShortSymbols properties.
So try this:
let dateFormatter: NSDateFormatter = NSDateFormatter()
let months = dateFormatter.shortMonthSymbols
let monthSymbol = months[month-1] as! String // month - from your date components
println(monthSymbol)
I am adding three types. Have a look.
//Todays Date
let todayDate = NSDate()
let calendar = NSCalendar(identifier: NSCalendarIdentifierGregorian)!
let components = calendar.components(.CalendarUnitYear | .CalendarUnitMonth | .CalendarUnitDay, fromDate: todayDate)
var (year, month, date) = (components.year, components.month, components.day)
println("YEAR: \(year) MONTH: \(month) DATE: \(date)")
//Making a X mas Yr
let morningOfChristmasComponents = NSDateComponents()
morningOfChristmasComponents.year = 2014
morningOfChristmasComponents.month = 12
morningOfChristmasComponents.day = 25
morningOfChristmasComponents.hour = 7
morningOfChristmasComponents.minute = 0
morningOfChristmasComponents.second = 0
let morningOfChristmas = NSCalendar.currentCalendar().dateFromComponents(morningOfChristmasComponents)!
let formatter = NSDateFormatter()
formatter.dateStyle = NSDateFormatterStyle.LongStyle
formatter.timeStyle = .MediumStyle
let dateString = formatter.stringFromDate(morningOfChristmas)
print("dateString : \(dateString)")
//Current month - complete name
let dateFormatter: NSDateFormatter = NSDateFormatter()
let months = dateFormatter.monthSymbols
let monthSymbol = months[month-1] as! String
println("monthSymbol : \(monthSymbol)")
Print Results:
YEAR: 2015 MONTH: 10 DATE: 9
dateString : December 25, 2014 at 7:00:00 AM
monthSymbol : October
Update Swift 5.x Solution:
Today is Monday, 20 April, 2020
let date = Date() // get a current date instance
let dateFormatter = DateFormatter() // get a date formatter instance
let calendar = dateFormatter.calendar // get a calendar instance
Now you can get every index value of year, month, week, day everything what you want as follows:
let year = calendar?.component(.year, from: date) // Result: 2020
let month = calendar?.component(.month, from: date) // Result: 4
let week = calendar?.component(.weekOfMonth, from: date) // Result: 4
let day = calendar?.component(.day, from: date) // Result: 20
let weekday = calendar?.component(.weekday, from: date) // Result: 2
let weekdayOrdinal = calendar?.component(.weekdayOrdinal, from: date) // Result: 3
let weekOfYear = calendar?.component(.weekOfYear, from: date) // Result: 17
You can get an array of all month names like:
let monthsWithFullName = dateFormatter.monthSymbols // Result: ["January”, "February”, "March”, "April”, "May”, "June”, "July”, "August”, "September”, "October”, "November”, "December”]
let monthsWithShortName = dateFormatter.shortMonthSymbols // Result: ["Jan”, "Feb”, "Mar”, "Apr”, "May”, "Jun”, "Jul”, "Aug”, "Sep”, "Oct”, "Nov”, "Dec”]
You can format current date as you wish like:
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
let todayWithTime = dateFormatter.string(from: date) // Result: "2020-04-20 06:17:29"
dateFormatter.dateFormat = "yyyy-MM-dd"
let onlyTodayDate = dateFormatter.string(from: date) // Result: "2020-04-20"
I think this is the most simpler and updated answer.
Swift 4.x Solution:
//if currentMonth = 1
DateFormatter().monthSymbols[currentMonth - 1]
Answer:
January
let now = Date()
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "LLLL"
let nameOfMonth = dateFormatter.string(from: now)
My current code:
if let var timeResult = (jsonResult["dt"] as? Double) {
timeResult = NSDate().timeIntervalSince1970
println(timeResult)
println(NSDate())
}
The results:
println(timeResult) = 1415639000.67457
println(NSDate()) = 2014-11-10 17:03:20 +0000 was just to test to see what NSDate was providing.
I want the first to look like the last. The value for dt = 1415637900.
Also, how can I adjust to time zone? Running on iOS.
You can get a date with that value by using the NSDate(withTimeIntervalSince1970:) initializer:
let date = NSDate(timeIntervalSince1970: 1415637900)
To get the date to show as the current time zone I used the following.
if let timeResult = (jsonResult["dt"] as? Double) {
let date = NSDate(timeIntervalSince1970: timeResult)
let dateFormatter = NSDateFormatter()
dateFormatter.timeStyle = NSDateFormatterStyle.MediumStyle //Set time style
dateFormatter.dateStyle = NSDateFormatterStyle.MediumStyle //Set date style
dateFormatter.timeZone = NSTimeZone()
let localDate = dateFormatter.stringFromDate(date)
}
Swift 3.0 Version
if let timeResult = (jsonResult["dt"] as? Double) {
let date = Date(timeIntervalSince1970: timeResult)
let dateFormatter = DateFormatter()
dateFormatter.timeStyle = DateFormatter.Style.medium //Set time style
dateFormatter.dateStyle = DateFormatter.Style.medium //Set date style
dateFormatter.timeZone = self.timeZone
let localDate = dateFormatter.string(from: date)
}
Swift 5
if let timeResult = (jsonResult["dt"] as? Double) {
let date = Date(timeIntervalSince1970: timeResult)
let dateFormatter = DateFormatter()
dateFormatter.timeStyle = DateFormatter.Style.medium //Set time style
dateFormatter.dateStyle = DateFormatter.Style.medium //Set date style
dateFormatter.timeZone = .current
let localDate = dateFormatter.string(from: date)
}
It's simple to convert the Unix timestamp into the desired format. Lets suppose _ts is the Unix timestamp in long
let date = NSDate(timeIntervalSince1970: _ts)
let dayTimePeriodFormatter = NSDateFormatter()
dayTimePeriodFormatter.dateFormat = "MMM dd YYYY hh:mm a"
let dateString = dayTimePeriodFormatter.stringFromDate(date)
print( " _ts value is \(_ts)")
print( " _ts value is \(dateString)")
For managing dates in Swift 3 I ended up with this helper function:
extension Double {
func getDateStringFromUTC() -> String {
let date = Date(timeIntervalSince1970: self)
let dateFormatter = DateFormatter()
dateFormatter.locale = Locale(identifier: "en_US")
dateFormatter.dateStyle = .medium
return dateFormatter.string(from: date)
}
}
This way it easy to use whenever you need it - in my case it was converting a string:
("1481721300" as! Double).getDateStringFromUTC() // "Dec 14, 2016"
Reference the DateFormatter docs for more details on formatting (Note that some of the examples are out of date)
I found this article to be very helpful as well
Here is a working Swift 3 solution from one of my apps.
/**
*
* Convert unix time to human readable time. Return empty string if unixtime
* argument is 0. Note that EMPTY_STRING = ""
*
* #param unixdate the time in unix format, e.g. 1482505225
* #param timezone the user's time zone, e.g. EST, PST
* #return the date and time converted into human readable String format
*
**/
private func getDate(unixdate: Int, timezone: String) -> String {
if unixdate == 0 {return EMPTY_STRING}
let date = NSDate(timeIntervalSince1970: TimeInterval(unixdate))
let dayTimePeriodFormatter = DateFormatter()
dayTimePeriodFormatter.dateFormat = "MMM dd YYYY hh:mm a"
dayTimePeriodFormatter.timeZone = NSTimeZone(name: timezone) as TimeZone!
let dateString = dayTimePeriodFormatter.string(from: date as Date)
return "Updated: \(dateString)"
}
func timeStringFromUnixTime(unixTime: Double) -> String {
let date = NSDate(timeIntervalSince1970: unixTime)
// Returns date formatted as 12 hour time.
dateFormatter.dateFormat = "hh:mm a"
return dateFormatter.stringFromDate(date)
}
func dayStringFromTime(unixTime: Double) -> String {
let date = NSDate(timeIntervalSince1970: unixTime)
dateFormatter.locale = NSLocale(localeIdentifier: NSLocale.currentLocale().localeIdentifier)
dateFormatter.dateFormat = "EEEE"
return dateFormatter.stringFromDate(date)
}
In Swift 5
Using this implementation you just have to give epoch time as a parameter and you will the output as (1 second ago, 2 minutes ago, and so on).
func setTimestamp(epochTime: String) -> String {
let currentDate = Date()
let epochDate = Date(timeIntervalSince1970: TimeInterval(epochTime) as! TimeInterval)
let calendar = Calendar.current
let currentDay = calendar.component(.day, from: currentDate)
let currentHour = calendar.component(.hour, from: currentDate)
let currentMinutes = calendar.component(.minute, from: currentDate)
let currentSeconds = calendar.component(.second, from: currentDate)
let epochDay = calendar.component(.day, from: epochDate)
let epochMonth = calendar.component(.month, from: epochDate)
let epochYear = calendar.component(.year, from: epochDate)
let epochHour = calendar.component(.hour, from: epochDate)
let epochMinutes = calendar.component(.minute, from: epochDate)
let epochSeconds = calendar.component(.second, from: epochDate)
if (currentDay - epochDay < 30) {
if (currentDay == epochDay) {
if (currentHour - epochHour == 0) {
if (currentMinutes - epochMinutes == 0) {
if (currentSeconds - epochSeconds <= 1) {
return String(currentSeconds - epochSeconds) + " second ago"
} else {
return String(currentSeconds - epochSeconds) + " seconds ago"
}
} else if (currentMinutes - epochMinutes <= 1) {
return String(currentMinutes - epochMinutes) + " minute ago"
} else {
return String(currentMinutes - epochMinutes) + " minutes ago"
}
} else if (currentHour - epochHour <= 1) {
return String(currentHour - epochHour) + " hour ago"
} else {
return String(currentHour - epochHour) + " hours ago"
}
} else if (currentDay - epochDay <= 1) {
return String(currentDay - epochDay) + " day ago"
} else {
return String(currentDay - epochDay) + " days ago"
}
} else {
return String(epochDay) + " " + getMonthNameFromInt(month: epochMonth) + " " + String(epochYear)
}
}
func getMonthNameFromInt(month: Int) -> String {
switch month {
case 1:
return "Jan"
case 2:
return "Feb"
case 3:
return "Mar"
case 4:
return "Apr"
case 5:
return "May"
case 6:
return "Jun"
case 7:
return "Jul"
case 8:
return "Aug"
case 9:
return "Sept"
case 10:
return "Oct"
case 11:
return "Nov"
case 12:
return "Dec"
default:
return ""
}
}
How to call?
setTimestamp(epochTime: time) and you'll get the desired output as a string.
Convert timestamp into Date object.
If timestamp object is invalid then return current date.
class func toDate(_ timestamp: Any?) -> Date? {
if let any = timestamp {
if let str = any as? NSString {
return Date(timeIntervalSince1970: str.doubleValue)
} else if let str = any as? NSNumber {
return Date(timeIntervalSince1970: str.doubleValue)
}
}
return nil
}
Swift:
extension Double {
func getDateStringFromUnixTime(dateStyle: DateFormatter.Style, timeStyle: DateFormatter.Style) -> String {
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = dateStyle
dateFormatter.timeStyle = timeStyle
return dateFormatter.string(from: Date(timeIntervalSince1970: self))
}
}
Anyway #Nate Cook's answer is accepted but I would like to improve it with better date format.
with Swift 2.2, I can get desired formatted date
//TimeStamp
let timeInterval = 1415639000.67457
print("time interval is \(timeInterval)")
//Convert to Date
let date = NSDate(timeIntervalSince1970: timeInterval)
//Date formatting
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "dd, MMMM yyyy HH:mm:a"
dateFormatter.timeZone = NSTimeZone(name: "UTC")
let dateString = dateFormatter.stringFromDate(date)
print("formatted date is = \(dateString)")
the result is
time interval is 1415639000.67457
formatted date is = 10, November 2014 17:03:PM
If you are maximizing the Codable protocol for parsing your JSON data. You could simply make the data type of dt as Date and do:
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .secondsSince1970
For me: Converting timestamps coming from API to a valid date :
`let date = NSDate.init(fromUnixTimestampNumber: timesTamp /* i.e 1547398524000 */) as Date?`
By using this code you will be able to convert timeStamp to Time and Date
let timeStamp = Date().timeIntervalSince1970
let date = NSDate(timeIntervalSince1970: timeStamp)
let dayTimePeriodFormatter = DateFormatter()
dayTimePeriodFormatter.dateFormat = "dd MMMM,YYYY.hh:mm a"
let dateTimeString = dayTimePeriodFormatter.string(from: date as Date)
let dateTime = dateTimeString.split(separator: ".")
print( "Date = \(dateTime[0])")
print( "Time = \(dateTime[1])")
Output:
Date = 19 January,2022
Time = 10:46 AM