Dateformatter Swift

broken image
Dateformatter Swift

SwiftUI's text views have an optional formatter parameter that lets us customize the way data is presented inside the label. This is important because often values are updated for us when something happens in our program, so by attaching a formatter SwiftUI can make sure our data looks right on. Support Swift by Sundell by checking out this sponsor: Emerge: Continuously monitor and reduce your app's size. Emerge's easy to use plugins for GitHub and fastlane will automatically scan your app's binary and provide you with simple, actionable suggestions on how to make it smaller and, in turn, faster for your users to download.

  • The above Swift code prints a date style that's common in The Netherlands, with dashes - and day-month-year. First, we're setting the locale to nlNL, and then we call setLocalizedDateFormatFromTemplate (:) with a custom date/time format.
  • Use DateFormatter to parse and format a date in Swift. The default time zone for a DateFormatter is the device's local time, so to obtain UTC time the timeZone value needs to be configured.
  • At WWDC19, Apple added a new RelativeDateTimeFormatter, which formats relative dates from the current date, for example by formatting a past date as 'X days ago' or today as 'today'. This guide explores how to display and format dates using many of the different date formatters built into Apple's platforms.
Exploring how to code for iOS in Swift and Objective-CLast updated on
Dateformatter

SwiftUI's text views have an optional formatter parameter that lets us customize the way data is presented inside the label. This is important because often values are updated for us when something happens in our program, so by attaching a formatter SwiftUI can make sure our data looks right on. Support Swift by Sundell by checking out this sponsor: Emerge: Continuously monitor and reduce your app's size. Emerge's easy to use plugins for GitHub and fastlane will automatically scan your app's binary and provide you with simple, actionable suggestions on how to make it smaller and, in turn, faster for your users to download.

  • The above Swift code prints a date style that's common in The Netherlands, with dashes - and day-month-year. First, we're setting the locale to nlNL, and then we call setLocalizedDateFormatFromTemplate (:) with a custom date/time format.
  • Use DateFormatter to parse and format a date in Swift. The default time zone for a DateFormatter is the device's local time, so to obtain UTC time the timeZone value needs to be configured.
  • At WWDC19, Apple added a new RelativeDateTimeFormatter, which formats relative dates from the current date, for example by formatting a past date as 'X days ago' or today as 'today'. This guide explores how to display and format dates using many of the different date formatters built into Apple's platforms.
Exploring how to code for iOS in Swift and Objective-CLast updated on

Now that we know a bit about Date and DateComponents, let's actually get a readable date in our Swift app, shall we? This is the job of DateFormatter. DateFormatter is a class that can take a Date, and output a String describing that time/date as its format instructions dictate. In other words, you tell it what you want to know, and it will give you a String that says that. It has a few pretty useful built-in formats, and the capability to accept a custom date format string.

There's not too much to the actual creation of an DateFormatter object. It pretty much just has an empty initializer (and an NSCoding one, but we aren't covering NSCoding today). After initializing your DateFormatter, you set the appropriate style for the date and time, and that's all you need.

Built-In DateFormatter.Style Values

As mentioned earlier, there are some built in formats used for date and time. Both the dateStyle and timeStyle properties take a value from the DateFormatter.Style enumeration. They interpret the enumeration differently, but they are expressive enough to be shared between them. Below is an example of what the various DateFormatter.Styles do for their respective output. These examples are for an en-US locale:

DateFormatter.StyleDate OutTime OutShortStyle12/25/197:00 AMMediumStyleDec 25, 20197:00:00 AM'LongStyleDecember 25, 20197:00:00 AM PSTFullStyleWednesday, December 25, 20147:00:00 AM Pacific Standard Time

Here's a bit of sample code to create the above Date (using DateComponents, which you can read about in the previous post DateComponents — Class Reference), and then using DateFormatter in Swift:

As you can see, you can set the dateStyle and timeStyle as different values. Also, like every use of enumerations in Swift, you can also use type inference and not write the enumeration's name each time if the property it is set to is already typed as that enum. After that, you just call the stringFromDate instance method of the DateFormatter object you created, giving the date you want it to format as an argument, and it will return a String containing that date in a human-readable format the way you told it to.

Custom Fixed DateFormatter Styles

To be honest, I've pretty much only used the built-in DateFormatter.Styles in what I've worked on, they did what I needed. However, if you do want to do something different, you can write your own custom format string. This string will be a series of characters that DateFormatter knows are stand-ins for the values you want to show, and then replace them with the appropriate values.

The character patterns used in these format strings are based on the Unicode Technical Standard #35. Apple's documentation for date formatting strings (available at Data Formatting Guide: Date Formatters) lists which revision of the standard is used for each iOS and OS X version up to OS X 10.9 and iOS 7. This has still not been updated to any later versions of the Operating systems, so I'm going to assume for now that it still is working with tr35-31.

As a side note, it would APPEAR that they are using at least revision 35. After some sleuthing, it responds correctly to the 'r' formatter, which did not appear until revision 35. I don't think there is much different for the Gregorian calendar though, so for now, I will write this assuming they are still using revision 31 at tr35-31.

So, basically, if you wanted to say something like, 'Wednesday, 7 AM', you would do something like this:

Below I have included a chart of what I think will be the most useful date field symbols. These are written from the perspective of an 'en-US' locale with the Gregorian calendar. If you want to see the full list, you can see it at the UTS #35-31: Unicode LDML: Dates.

FormatDescriptionExample'y'A year with at least 1 digit.

1 AD → '1'

42 AD → '42'

2014 AD → '2014'

42 AD → '42'

2014 AD → '14'

42 AD → '042'

2014 AD → '2014'

42 AD → '0042'

2014 AD → '2014'A month with at least 1 digit.

July → '7'

December → '12'

December → '12'Three letter month abbreviation.

July → 'Jul'

December → 'Dec'Full name of month.

July → 'July'

December → 'December'

July → 'J'

December → 'D'A day with at least 1 digit.

4 → '4'

25 → '25'

25 → '25'3 letter day abbreviation of day name.

Wednesday → 'Wed'

Thursday → 'Thu'Full day name.

Wednesday → 'Wednesday'

Thursday → 'Thursday'Dateformatter Swift

Not unique, Tuesday and Thursday are both 'T'.

Wednesday → 'W'

Thursday → 'T'2 letter day abbreviation of day name.

Wednesday → 'We'

Thursday → 'Th'Period of day (AM/PM).

5 PM → 'PM'

7 AM → 'AM'A 1-12 based hour with at least 1 digit.

5 PM → '5'

7 AM → '7'

7 AM → '07'A 0-23 based hour with at least 1 digit.

5 PM → '17'

7 AM → '7'

7 AM → '07'A minute with at least 1 digit.

40 → '40'

1 → '1'

1 → '01'A second with at least 1 digit.

40 → '40'

1 → '1'

1 → '01'Tenths place of fractional second.

123 ms → '1'

7 ms → '0'

7 ms → '00'

7 ms → '007'

Two things to note about the fractional second. First, it does not round, it just shows the appropriate places (otherwise the 2 digit fractional second would show 7 ms as '01'). Secondly, the Unicode standard lets you use as many as you want, so 'SSSSS' is valid. However, DateFormatter will not show anything below milliseconds, it will just show 0s below that. So 123456789 nanoseconds with a 'SSSSSSSSS' format string will show up as '123000000'.

One major thing to note, there is a difference between 'yyyy' and 'YYYY'. In most cases, you probably want to use the lowercase one, 'yyyy'. The uppercase one is the 'Week of Year' style of year. If you're curious about the 'Week of Year' style of year, it is based off of something called the ISO Week Date, which is part of the ISO 8601 standard. You can read more about it on this Wikipedia page.

Suffice it to say though, you want to usually use 'yyyy' in your DateFormatter, unless you are writing a Swift app for an institution that needs to use the ISO Week Date.

Now, there is one issue with using the fixed format style of custom formats. The reason they are called 'fixed formats', is because they print out exactly what you say, in the same order. That's all well and good in your locale and calendar system, but (especially with the short date style) 06/02/2014 and 02/06/2014 are very different dates. One is the day Swift was released, the other is Rick Astley's 48th birthday. If I gave a custom format string of 'MM/dd/yyyy' to show Swift's birthday to app users in Great Britain, they'll be wondering if I Rickrolled them.

Luckily, Apple built-in a great method to DateFormatter to help us avoid this accidental Rickrolling.

The dateFormatFromTemplate method

You tell this DateFormatter class method what components you want, using the same format strings as used in the fixed format, and a locale, and it will give you a date format string that is appropriate for your locale. A very similar example of this was done in Apple's Documentation: Data Formatting Guide: Date Formatters. So, let's tell it to generate the appropriate format strings for the en-US locale, and the en-GB locale:

There are a few things to notice about this method. Firstly, to repeat, this is a class method, so it is being called on the DateFormatter class itself, not a specific instance of it.

Secondly, the template used is the same. It can be in any order, I just chose my default of the US order. It just needs to know what components you want, it will figure out what to do with them based on the locale specified.

Thirdly, ignore the options method. It appears to be there in case options are needed later, but according to the docs, there are no options defined yet, and you should just give it 0.

Fourthly, you probably would use Locale.current for the locale parameter. Unless you are trying to show how different locales and calendars would show the date provided, the 'current' constant will show what makes sense for that user's iOS device. I just hard coded it here to show it explicitly in the code what it was set to.

Finally, this actually returns an optional string, probably in case it cannot make a suitable dateFormat String from the template provided.

So now, we can use this like we used the fixed custom format string, by setting an instance of DateFormatter's dateFormat property to it:

There, now I won't accidentally Rickroll my friends at @SwiftLDN, or other readers in Great Britain.

Conclusion

After realizing the inverted date of Swift's announcement was Rick Astley's birthday, I had trouble not using a Rick Astley song title pun as the title to this post.

Much like how DateComponents made it a lot easier to work with Dates in your Swift code, with setting the individual components directly, DateFormatter gives you a lot of power in how you want an Date to appear to your Swift app's users. There is even more power than what I showed here, but I felt that the chart would be big enough without including less used components like the quarter or theISO Week Date style of years. Nonetheless though, you can check those out at the Unicode Standard to get the rest of the values if you need them for your instance of DateFormatter.

Dateformatter Swift Locale

This of course was the Swift version of how to use DateFormatter. If you want to see how to use it in Objective-C, check out the previous post Displaying a human readable NSDate.

I hope you found this article helpful. If you did, please don't hesitate to share this post on Twitter or your social media of choice, every share helps. Of course, if you have any questions, don't hesitate to contact me on the Contact Page, or on Twitter @CodingExplorer, and I'll see what I can do. Thanks!

Sources

  • DateFormatter Class Reference – Apple Inc.
  • Data Formatting Guide: Date Formatters – Apple Inc.
  • UTS #35-31: Unicode LDML: Dates – Unicode, Inc.

Question or problem with Swift language programming:

How do you create a date object from a date in swift xcode.

eg in javascript you would do:
var day = new Date(‘2014-05-20');

How to solve the problem:

Solution 1:

Swift has its own Date type. No need to use NSDate.

Creating a Date and Time in Swift

In Swift, dates and times are stored in a 64-bit floating point number measuring the number of seconds since the reference date of January 1, 2001 at 00:00:00 UTC. This is expressed in the Date structure. The following would give you the current date and time:

For creating other date-times, you can use one of the following methods.

Method 1

If you know the number of seconds before or after the 2001 reference date, you can use that.

Method 2

Of course, it would be easier to use things like years, months, days and hours (rather than relative seconds) to make a Date. For this you can use DateComponents to specify the components and then Calendar to create the date. The Calendar gives the Date context. Otherwise, how would it know what time zone or calendar to express it in?

Other time zone abbreviations can be found here. If you leave that blank, then the default is to use the user's time zone.

Method 3

The most succinct way (but not necessarily the best) could be to use DateFormatter.

The Unicode technical standards show other formats that DateFormatter supports.

Notes

See my full answer for how to display the date and time in a readable format. Also read these excellent articles:

Solution 2:

This is best done using an extension to the existing NSDate class.

The following extension adds a new initializer which will create a date in the current locale using the date string in the format you specified.

Now you can create an NSDate from Swift just by doing:

Please note that this implementation does not cache the NSDateFormatter, which you might want to do for performance reasons if you expect to be creating many NSDates in this way.

Please also note that this implementation will simply crash if you try to initialize an NSDate by passing in a string that cannot be parsed correctly. This is because of the forced unwrap of the optional value returned by dateFromString. If you wanted to return a nil on bad parses, you would ideally use a failible initializer; but you cannot do that now (June 2015), because of a limitation in Swift 1.2, so then you're next best choice is to use a class factory method.

A more elaborate example, which addresses both issues, is here: https://gist.github.com/algal/09b08515460b7bd229fa .

Update for Swift 5

Solution 3:

Swift doesn't have its own Date type, but you to use the existing Cocoa NSDate type, e.g:

Which you can use like:

Solution 4:

Here's how I did it in Swift 4.2:

Usage:

Solution 5:

According to Apple documentation

Example :

Hope this helps!





broken image