After a few hours of working with NSCalendar, NSDate and NSDateComponents, it occurred to me that Apple did not create an enumeration for weekdays.
Apparently, judging by the framework, all world is using the 7 days in a week approach to week days..and those week days have names that are universal in meaning i.e. a translated Sunday to for example hungarian is a different word (Vasarnap) but it MEANS Sunday. I speak hungarian + 4 other languages besides english so I know for sure.
If we extract the NSCalendarUnitWeekDay component, we can quickly find out that it returns NSInteger, and Sunday is represented by 1, Monday is 2, etc..
It is very easy to extend NSCalendar to provide such enumeration and I already did that actually and so far it turns out to be practical.
But I am wondering perhaps I am missing something and there is a reason for omitting such enumeration.
Is there?
There is not. It does seem strange but the only reason I can think of for not including an enum is that due to localization, the "meaning" of the 1, 2, 3, etc would change and by defining an enum for the Gregorian calendar, this would lead to an implied assumption that Sunday=1 which is only correct some calendars.
Related
If you're used Cocoa for a while you're probably familiar with NSDateFormatter
and NSNumberFormatter. They're handy for creating formatted display strings from dates and numbers, or for converting date or number strings into numeric values, while supporting different languages and locales.
A few weeks ago I stumbled on NSDateComponentsFormatter, which lets you create formatted time intervals like "4 hours, 37 minutes and 17 seconds." Pretty cool.
There's also the related NSDateIntervalFormatter, which creates strings by comparing 2 dates.
Then there are some REALLY obscure NSFormatter subclasses:
NSMassFormatter
NSByteCountFormatter
NSLengthFormatter
NSEnergyFormatter
NSPersonNameComponentsFormatter
EDIT:
From the comments, I've aded NSPersonNameComponentsFormatter.
Searching on "NS*Formatter" in the Xcode help system reveals most of these, but not all. (It looks like the help text has to be indexed correctly in order for searching to work, which is annoying.)
That brings the total I have been able to find to
NSDateIntervalFormatter -Difference between 2 dates
NSDateComponentsFormatter -NSDateComponents to/from string
NSDateFormatter -Formats NSDates as strings
NSNumberFormatter -Formats numbers as strings
NSMassFormatter -Formats mass quantity as strings
NSByteCountFormatter -Formats byte counts in K, MB, GB, etc.
NSLengthFormatter -Formats length values
NSEnergyFormatter -Displays energy qualities in Joules or Calories
NSPersonNameComponentsFormatter - displays localized formatted names
Annoyingly, it looks like many of these formatters don't have a locale property, so it's not very easy to use them to create formatted strings in languages/locales other than the system's default locale. If I'm missing something, please tell me.
Does anybody else know of other formatters I'm missing? These are pretty obscure, but could save you a lot of time if you were to need them.
EDIT #2:
Question part 2: Is there a way to get output from the formatters that lack a locale property in locale's other than the system default locale? It seems silly that they don't ALL have and honor a locale property. It's pretty common to need to generate output for languages/locales other than the current locale.
There's no need to search. The NSFormatter documentation lists all of its subclasses. Look at the top of the page, in the "inherits from" block.
Note that this information is not available in the Xcode 7.3 doc reader. It's only available in the online docs (or by using the excellent Dash reader).
I went into
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/System/Library/Frameworks
and then did
for header in **/*.h; do ack -o 'NSFormatter' "$header"; done
which gave me some interesting ones:
NSPersonNameComponentsFormatter
CNContactFormatter
CNPostalAddressFormatter
DRMSFFormatter
MKDistanceFormatter
Doing the same for iPhoneOS.sdk didn't turn up any new NSFormatter subclasses.
I am writing a Swift app and am dealing with decimals in a database (stored in mysql as decimals, with 2 digits. Basically it's sales someone made each day, so generally anything from $0 to $1000, but not millions, and nothing insane in terms of trailing decimals, just always rounded to 2 decimal places).
Referencing this helped me out:
How to properly format currency on ios
..But I wanted to just do a quick sanity check here and make sure this strategy is ok.
i.e I would use NSDecimal or NSDecimalNumber (is there a preferred swift equivalent??)
What would you all recommend I do when dealing with currency in Swift? I'd like to use the locale-based currency symbol as well. I have a class called Sales that contains the amount in question. What do you recommend the datatype to be?
Apologies if I am coming off lazy, I actually have some ideas on what to do but feel a little overwhelmed at the "right" approach, especially in a locale-sensitive way, and wanted to check in here with you all.
Thanks so much!
Update for Swift 3: A Decimal type is now available with built-in support for operators like *, /, +, <, etc. When used in an Any context (passed to Objective-C), it's bridged to NSDecimalNumber.
Old answer:
NSDecimal is not really supported in Swift (it's a weird opaque pointer type), but NSDecimalNumber is — and as in Obj-C, it's the best thing to use for base-ten arithmetic (because it actually does its operations in base ten). NSLocale, NSNumberFormatter and friends all work too and should satisfy your localization needs.
Swift 3 now has a Decimal (value) type which is bridged to NSDecimalNumber.
What is the standard way to present the ambiguous extra hour when winter time begins?
So far i used localized time formats to display and parse dates and times. E.g. 1. January 2014, 15:27.
I'm using location based time zones like "Europe/Berlin".
And i can't just change to plain GMT offsets because i do need to perform calculations on the dates. Otherwise i would get the wrong absolute time when moving across DST change dates.
All this works fine except for the one hour at the end of DST (e.g. October 26th 2014, 2am-3am) which occurs twice. I need to present it in a way that i can later parse again.
Is there a stadardized format? Do i just add a custom symbol? Do i use the GMT offset additionally to the geographic time zone? And how do i know when to use this special format - because i don't want to print it all the time, since it's redundant most of the year.
The answer by Matt Johnson is correct and insightful.
Java 8 & java.time.*
Let me add another to his list, from the new java.time.* classes bundled with Java 8 and defined by JSR 310. These new classes are inspired by Joda-Time but are re-architected.
The default used by java.time.ZonedDateTime is one concatenated string using square brackets around the time zone name and no spaces.
2014-10-26T13:49:48.278+01:00[Europe/Berlin]
#MattJohnson Feel free to merge this answer's content with yours if you wish.
There isn't a standard that combines everything. The closest you can get is with two fields. One which would be an ISO8601/RFC3339 Date+Time+Offset, and another which would be the IANA/Olson time zone.
Depending on your platform, you may have a single object that represents both, such as a DateTime in Joda-Time or a ZonedDateTime in Noda Time. But there is no standardized representation of this as a string.
Here are some that I have seen though:
Two completely separate strings:
"2014-10-26T02:00:00+01:00"
"Europe/Berlin"
One concatenated string, space separated:
"2014-10-26T02:00:00+01:00 Europe/Berlin"
One concatenated string with a space and using parentheses:
"2014-10-26T02:00:00+01:00 (Europe/Berlin)"
One concatenated string without any space, but with square brackets: (thanks Basil)
"2014-10-26T02:00:00+01:00[Europe/Berlin]"
As JSON, with some predetermined field names:
{
value: "2014-10-26T02:00:00+01:00",
zone: "Europe/Berlin"
}
As XML, with some predetermined attribute names:
<TimeStamp Value="2014-10-26T02:00:00+01:00" Zone="Europe/Berlin" />
As XML, with some predetermined element names:
<TimeStamp>
<Value>2014-10-26T02:00:00+01:00</Value>
<Zone>Europe/Berlin</Zone/>
</TimeStamp>
Any of these would be acceptable. Pick the one that fits your situation, or adapt to something similar.
Regarding your question:
... how do i know when to use this special format ...
When you're recording an event that has already passed and cannot be changed, then you do not need to store the time zone. The date+time+offset value alone is sufficient. Otherwise, you need both.
I have a shell script (zsh, to be precise) which uses
strftime "%I:%M %p %Z (%a, %b %d)" "$EPOCHSECONDS"
to generate a "current time" such as
"02:45 PM CST (Thu, Mar 01)"
This needs to be able to display the time in several different USA timezones, and so I have been using 'US/Eastern', 'US/Central', and 'US/Pacific' like so:
export TZ='US/Eastern'
strftime "%I:%M %p %Z (%a, %b %d)" "$EPOCHSECONDS"
That seems to work just fine, and I prefer it to using TZ='America/CityName' because it doesn't require me to know which city is in which TZ, I just need to tell it which TZ I want.
However, I happened across http://www.php.net/manual/en/timezones.others.php and saw that it says
Please do not use any of the timezones listed here (besides UTC),
they only exist for backward compatible reasons.
I don't know what the issues are with the US/Region names, but I'm curious to know if using them is likely to cause a problem in the foreseeable future, or are they still safe to use? Is it just PHP which doesn't like them, or is everyone moving away from them?
The standard format for naming timezones in the Olson database is Continent/City. The "old" names you mention like US/Eastern, US/Central, and many more, are listed as backward compatibility links in the tzdata source distribution (in the file "backward"). According to the comment at the top of the file, these names may have become backward compatibility links in late 1993.
I think I remember reading that this standard was adopted because it was felt to be more stable: geopolitical (country) boundaries change, cities never move around. Maybe also because names like "Eastern" and "Central" are thought to be more confusing because they mean different timezones in different parts of the world. However, I cannot find any references to the naming rationale at the moment, so don't quote me on this.
The Continent/City-style names are preferred. Notice that operating systems like Debian and Ubuntu ask you to select the system timezone using these names (unless they autodetect it at installation time), Using these names you wouldn't really be required to, as you say, "know which city is in which TZ" because the city name is, well, part of the timezone name! So if you happen to have learned the Continent/City names instead of or in addition to the Country/Region names, you're already OK.
That being said, I do not think that these names will ever disappear. On the timezone mailing list, they are definitely always called "backward compatibility", not "deprecated", and are intended to stay, notwithstanding what PHP recommends.
I did some searching but haven't landed anything that looks useful yet but I am wondering if anyone knows of something (tool,lib etc) that can parse English phrases and translate them into a cron string.
For example: Every Tuesday at 15:00 converts to 0 15 * * 2
It seems like something that would have lots of gotchas and it would be preferable to benefit from someone elses work. You see it in a few nice sites/apps that can work out what you mean from a simple phrase rather than having some hideous user interface.
Thanks in advance.
Though this is an old question I would like to list out all libraries/tools that I know so far, so that this answer might help others who arrive on this page looking for the same thing:
JavaScript:
natural-cron.js (link)
friendly-cron (link)
PHP:
natural-cron-expression (link)
Ruby:
whenever (link)
Feel free to reply in comments, if you know about any other library which is not listed here :)
(Full disclosure: natural-cron.js has been developed by me & my friend, when no other library satisfied the needs of our project)
For Ruby there's "Whenever" which might provide a starting point: It translates quasi-english (actually it's valid Ruby) into cron strings.
Depending on how flexible you need it to be, and how willing to roll up your own sleeves you are, you could define a simple grammar for this.
Every would be a quantifier. You may need others but I can't think of any. Valid syntax might be:
Every (day-spec) AT (time)
Where day-spec could be a literal day (ie. Monday) or be a day of the month (ie. 30th Day) or some other syntax (I'd suggest fortnights but I'm not sure if Cron can represent those well).
Time could be specified using either 24 hour (16:00) or 12 hour (4:00pm) format.
Another syntax that you might want is:
Every (frequency) From (time) where frequency is basically (quantity) (unit) (ie. 10 Minutes). The from time enables you to set an offset (eg. Every 30 Minutes From 01:10am).
You'd probably need to sit down and figure out these details a bit more. But a rigid grammar could be implemented relatively easily using recursive descent.
Hmm, about those gotchas... How about also writing one that translates the cron params back to English? That way you can see if the parser "understood" you.