Users will enter dates in my cocoa (core data) app. How to choose right date format? - validation

I am working on my first application for mac which uses Core Data. Since I don't have much software development experience I would like to ask the more experienced developers the following question:
When entering data in some of the forms, user will have to enter a date in couple of the forms. Since app will be on app store and people from different continents will download it (I hope so) I am thinking of allowing the user to select his preferred date format from the preferences panel that I have in my app.
But I am wondering what will happen if after entering 500 or more records, he decide to change the date format again? Will that cause a mess in core data eventually?
Is this good idea or I should keep things simple and just get the system date (user computer date format) and use that date format? What would you do? Any advice will be deeply appreciated.

My advice is to keep date as timeinterval. You can see such method for NSDate.
The interval between the date object and 00:00:00 UTC on 1 January 1970.
So if you get NSDate object from NSDatFormatter object you will be able to obtain time in seconds since 1970. You could store this value in Core Data and use it later for creating NSDate objects. You will be able to use it for different locales and time zones as well as use the correct format.
'Dates' is complex topic and I suggest you to read guides about dates and date formatters.

First is to decide how you should store the date. The answer here is as an NSDate. The NSDate is a single unique precise point in time, thus it in a sense stores both date and time.
This means that for example 1 PM in Berlin and 8 pm in Kuala Lumpur will be the exact same NSDate value (during winter months) but 2 pm in London and 2 pm in Paris the same calendar date will not be the same NSDate value. This is a quite complex topic, read the date and time programming topics documentation from Apple.
Then as you say you need to allow you user to input the date. The way to do that is to use a NSDateFormatter tied to your input control. The formatter can be defined to be as per system settings, which means you will get the localisation you are seeking for free, so that is in fact easy.
The tricky thing you are really facing is to determine what you are really looking to store if it is only the calendar date without an associated time you want to store. For example you decide store the date combined with 12.00 noon in the local timezone. Then if the user shifts to another timezone more than 12 hours away the date may be displayed as the previous date or the next. The safest bet is to store the date combined with 12:00 noon GMT as this is in the middle of the time zone range. There are a few locations 13 and 14 hours off that could exhibit the mentioned problem anyway, but these are small atolls in the pacific and could possibly be safely ignored.
However the the best thing is if you can in fact determine that what you are looking to store is really a precise point in time rather than a date (which is a 24 hour fuzzy definition). For example in a calendar app an event usually takes place at a specific time on a specific date, then store that time and date.

Related

Is the day of the week for a date the same everywhere in the world?

Part of my program requires checking the day of the week that a file was created. I have an input attribute which gives the date of creation in US form (month/day/year). However I do not have the day of the week.
As per the sadism of the legal department I am also restricted to only the time modules within python's standard library so unfortunately the obvious solution of PYTZ is not an option.
My current approach is to use the date to reference the Gregorian calendar. On the assumption that a the same date is always the same day i.e. 1st September 2022 is a Thursday everywhere in the world. However, I have not been able to validate this assumption.
If you know if this assumption is correct/incorrect and/or know of somewhere I can find out I would be very grateful.
Thanks.

Should I store the local time for events instead of UTC?

I am currently storing events of some entities in UTC time but I am not sure if I should do that in this case. Imagine there's an event at 10pm local time (-4h UTC) and a mobile App fetches "todays events". This could e.g. look like this:
App sends request to fetch all clubs in the near location
After receiving all clubs it sends a request to get all events for today. It therefore sends the local time Sun. 10pm to the server.
The server would convert the local time of the mobile device to UTC Mon. 1am and fetch all events from Monday. But of course that was not what I wanted.
Fetching all events from the clubs and convert them to their local time using their local time offset information is not really a great solution.
So wouldn't it be better to just store all events in local time? In that case the mobile App would send its local time to the server which would be able to query all events from the clubs in local time as well.
This sounds much simpler to me but I am not sure if I overlook something.
So what would I do in this case?
Yes, storing everything in UTC is probably the best solution.
You don't say how you are "storing" the dates/times, but if you are using Dates or Joda equivalents, then you should know that their underlying representation is effectively in UTC (they represent a moment in time as an offset in milliseconds since the "Epoch", which is Midnight, Jan 1, 1970 UTC). These dates only have a timezone when you format them as Strings.
Most databases do something similar (store the date in a common timezone, usually UTC). The major exception that I've found is the generally available date-time related column types in MS SqlServer which by default store everything in the local timezone of the server.
Also be aware that if you use SQLite, and you store a date/time by passing a String in SQL that contains a timezone, SQLite will store it without warning, but will ignore the timezone and assume that the timezone is UTC, giving you a result other than what you might expect.
For more on this, see my (old) blog post at http://greybeardedgeek.net/2012/11/24/java-dates/
The other answer is correct. Some more thoughts here.
A time zone is more than the offset from UTC mentioned in the Question. A time zone is also the set of past, present, and future rules for anomalies such as Daylight Saving Time. You should refer to a time zone by its proper name, continent plus Slash plus city or region. Never use the 3-4 letter codes such as EST or IST.
To search for events in the user's "today", you must know the user’s time zone. For example, a new day dawns earlier in Paris than in Montréal. After the stroke of midnight in Paris we still have a few hours of “yesterday” left to go in Montréal.
While you can make a guess as to the user’s time zone, the most reliable way is to ask the user.
DateTimeZone zone = DateTimeZone.forID( "America/Montreal" );
DateTimeZone now = DateTimeZone.now( zone );
DateTime today = now.withTimeAtStartOfDay();
DateTime tomorrow = today.plusDays( 1 );
// Search for events that start >= today AND that start < tomorrow.
To search Joda-Time objects, use the Comparator built into DateTime. That comparator works across objects of various time zones.
To query a database, convert that pair of DateTime objects into java.sql.Timestamp objects. You do that by extracting and passing the count of milliseconds since the epoch of 1970 in UTC.
long m = today.getMillis();
java.sql.Timestamp tsToday = new java.sql.Timestamp( m );

How did windows/c# remember the current systems year/date

Recently i was working with unit testing for my project.
I've given a task to test the method. The method should return the recent quarter date as per the current system date.
So, I've called the current system date using the following c# code:
string currentYear = DateTime.Now.ToString();
When i run the query it worked as expected.
So, its time for my tactics to raise a bug for that method. Hence I've changed the system date to 10/01/14 (dd/mm/yy).
Also I've customized current system date format to only keep last two digits of the year.
Ex: if year is 2014 the it shows only 14.
You can observe the short date and the long date in the following image.
When i run/debug the test in Visual Studio 2012, it still displays as 2014 as the current system date though I've modified it to 14.
Question: The real question is how did the system/program took the current year as 2014 even the system date is changed to 14. It may be silly but my doubt is Why it is not 1914 or 1814 and why it is 2014 ?.
Where did it store the current date or year information ? Does windows manage this stuff or did the C# taken care of the date ?
The real question is how did the system/program took the current year as 2014 even the system date is changed to 14. It may be silly but my doubt is Why it is not 1904 or 1804 and why it is 2014 ?.
C# only retrieved the date from the system, it was Windows that determined what data to send.
In the case of two-digit dates, Windows allows you to define what they mean in the Regional and Language applet in the Control Panel. This way you can specify the range you want it to represent depending on your usage.
The display of a date is not how it is stored, just how it is displayed.
January, 1st, 2014 may have a multitude of different formats, e.g.
2014-01-01
01-01-2014
01-01-14
1/1/14
Jan/1/14
001-2014
But all are held internally exactly the same way.
Note the advanced settings on your screenshot - this will indicate to many windows programs how to interpret a year entered as 2 digits, so it knows if it should regard a date entered as XX as 19XX or 20XX - this will cover manually entered dates, not the system date
Your C# application didn't store that date, Windows handled it for you.
As Sean mentioned, by changing from YYYY to YY you only changed how the date is displayed, not how it is stored. Windows doesn't store its system time information into a specific date format. Instead, it records the number of 100-milisecond intervals since 00:00 January 1st, 1601. That way it keeps the tracking of time independent of how it's displayed and allows you to display the date and time in a number of different formats.
As a curiosity, that specific date was chosen because the Gregorian calendar operates on a 400-year cycle (when it starts to repeat itself) and 1601 was the first year of the cycle that was active when Windows NT was being developed.
On a side note, Unix systems store that information as Unix Time or POSIX Time, counting the number of seconds elapsed since 00:00 January 1st 1970.

query by date vs query by time

I assume that application code should store time in database always as UTC ( punch me if I am wrong)
Now lets say I want to query everything between 23-mar-2013 to 24-mar-2013 . Should I create a time object and then query something like "23-mar-2013:00:00:00UTC" to "24-mar-2013:24:00:00UTC" or querying just by date is right "23-mar-2013" to "24-mar-2013".
Now the problem comes when I am not in UTC and in a time zone like -7:30 .
Now date queries would go wrong..
So does that mean I should query always with time ?
I am talking in concern to ElasticSearch, Tire, Ruby ( But I think that shouldn't matter)
The implementation absolutely does matter. Querying against one database or another is very different depending on how that database stores date / time values. I suggest you edit your question and make it specific for the technologies that you are using. Show some code if you can.
In general though, you are mixing two concepts and you should probably try to separate them mentally.
The moment something happened, an event time, can be measured by a DateTime combined value - represented as either UTC, or as a value that is offset from UTC where the offset is known. This is often referred to as "Instantaneous Time", "Universal Time", or "Physical Time".
The values that we give to dates and times when talking about them locally, such as "Today", "Yesterday", or "March 29, 2013". Even when we have a time, we are talking about a fraction of a day on a calendar. This is often referred to as "Calendar Time", "Local Time" or "Civil Time".
You can always query and do math with Instantaneous Time. It's unambiguous. However, the concept of "Today" is meaningless. There is no observer to mark the end of one day and the start of the next. (One could argue that the observer is in London, but that's not true during BST.)
Calendar Time is only suitable for querying or math when you have day-level precision and only one observer. So it usually makes a poor representation of something meant to be universal, like an event.
Let's go back to your original question. You said:
I want to query everything between 23-mar-2013 to 24-mar-2013
Right there - you have a problem. What is the context? Who's calendar dates are you talking about? Even though you said March 23, you probably don't mean March 23rd at midnight UTC to March 24th at midnight UTC. You probably mean some other calendar's midnights.
Keep in mind that not every day is 24 hours in length. When time zones switch on and off of daylight savings time (or summer time), the days could be 23 hours or 25 hours in length.
So what to do? First, you need a Time Zone database (like the IANA/Olson/TZ/TZDB/ZoneInfo database for example) Here is one implemented in Ruby.
Now, you need to to know the local time zone of the user. That is - the person that is asking the question that you are showing the query results to. That will involve your own application logic, maybe a selector or picker. If this is a web app, you might want to look at this map-based timezone picker, or at jsTimeZoneDetect.
You should always store events with instantaneous time. Let's just say you store events as UTC (although you might use an offset, we'll ignore that for now).
So you need to know for the date range that the user wants, what UTC times do the start and end dates of your query map to? For example, say we are in India using the Asia/Calcutta time zone. We would convert 23-mar-2013 00:00 - 24-mar-2013 00:00, to the UTC equivalent 22-mar-2013 18:30 - 23-mar-2013 18:30.
Then you can use those UTC DateTime values to query the database.
When you return the results to your user, you will probably want to convert UTC back to local time so they understand the results they are looking at.
You should also read the many great suggestions in this post.

How to change the starting date of a Calendar Year to something other than Jan 1st?

I'm writing an app that relies on the calendar and calendar events to display data to the user.
I need to be able to let the user select the beginning of his/her 'fiscal' year in settings, which will be the 1st of any of the 12 months. This is an app for military users, and any given unit's fiscal year can begin on whatever month their unit (base) decides.
The data I'm displaying to the user needs to be divided into 'fiscal' quarters according to the user's setting of the beginning of the fiscal year, not calendar year.
I'm not having problems retrieving, editing or deleting the events, I can't figure out how to change the beginning of the year to anything besides Jan 1st.
I found NSDateCategoryForReporting on GitHub, that seems like it's exactly what I need, but how do I tell it that the year begins on the 1st of x month?
iOS doesn't natively support this, so you'll have to find a plugin to do this or write your own. Your best bet is to write a class that performs the date conversions using the standard NSDate, NSCalendar, etc.
For instance, you could store what day the user specifies as their starting fiscal year. Then you can calculate the number of days difference between that and January 1st, and just shift dates based on that.

Resources