Mongoid DateTime: What is the right date? - ruby

I'm using Mongoid to store DateTime. But now i'm confusing with the real date.
In mongodb , the date is stored as:
{"2013-01-14T12:50:00.000Z"}
But when i print that value, it says:
2013-01-14T19:50:00+07:00
I don't really understand whether those Date formats are the same, and which one is "right" in my current timezone ?
Thank you for your help.

Date is stored in GMT, when "printed", it is displayed in your local timezone (GMT+7?)

The default Ruby date object should be able to handle offsets in time:
http://ruby-doc.org/stdlib-1.9.3/libdoc/date/rdoc/Date.html
Whereby some way down the page it even talks about how to start manipulating it I believe:
An optional argument the offset indicates the difference between the local time and UTC.
I do believe that mongoid is already converting the time for you as can be seen by the T value within the iso date being 7 hours ahead:
2013-01-14T19:50:00+07:00
Merely if you were to print the date and/or time instead of the full output with the offset included I have no doubt you will get the real date.
I believe mongoid most likely prints the offset even when it is applied because that offset IS there (since the time is off-setted by 7 hours from UTC) it is just not applied further.

Related

Changing format of date without using to_char - Oracle

I have to get the max payment date on an invoice and I am having trouble with the date format. I do not need the max in this formula as I am using the format in a reporting tool that is pulling the max from what it finds for me.
Using "to_char({datefield},'mm/dd/yyyy')" works for displaying that date the way we would like BUT when you use summary function MAX it does not pull the correct date because it is looking at a string and not a date (it will think 12/3/21 is larger than 3/2/22).
Another thing I have tried is trunc - "trunc({datefield})" which gives us the correct max date but it changes the formatting. For example if the date prior to the formula being applied is "8/12/21 12:00:00:000" the trunc formula will display it as 12-08-21 which is horribly wrong.
Long story short is I need a way to change a date/time to date with the format of 'mmmm/dd/yyyy' WITHOUT converting it to a string with something like to_char. Thank you!!!!
A DATE is a binary data type consisting of 7 bytes representing: century, year-of-century, month, day, hour, minute and second. It ALWAYS has all of those components and it is NEVER stored with any (human-readable) format.
What you are seeing when a date is displayed is the client application you are using to access the database making a decision to be helpful to you, the user, and display the binary DATE provided by the database in a human-readable format.
If you want to change how the DATE is displayed then you either need to:
Change the settings on the client application that controls how it formats dates when it displays them to you; or
Change the data-type so that it is no longer a DATE (which does not have a format) to a data type where the values of the date can be formatted (such as a string). You can do this using TO_CHAR.
If you want to find the maximum then do it BEFORE applying the formatting:
SELECT TO_CHAR(MAX({datefield}),'mm/dd/yyyy')
FROM your_table;

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

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.

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 );

UTC DateTime problems

I currently store all dateTimes in the DB as UTC dates. Each users time zone offset is also stored in the DB. When I retrieve a Date it is converted back to their local date using this offset.
The problem occurs when I retrieve a date using an ajax call. The date (which is already converted using the offset) is, I think, returned as a Java Date object. The browser then decides to mess with my Date adding the clients computers time zone offset to the Date object. This is causing dates to be a day ahead of what they should be if the time component is more than 11.59am.
The only solution I can come up with is to pass them as strings in which case this of course wouldn't happen. This is a laaaast resort for me though and I would love to find a better solution or workaround for this problem.
Your browser is not messing with the dates given that browsers don't have a native date transfer variable. You have something else that is doing that. How are you sending your dates in ajax? Json? Json will only send numbers or strings. XML will only send strings.
Something is converting your sent date into a javascript date object, find out what it is.

Significance of date 02/31/2157?

I work in a large scale IT support environment. Twice now we have seen an invalid date of 02/31/2157 being inserted in an Oracle DATE column. So far I have not been able to reproduce this problem, but it appears to be happening occasionally when a user attempts to save '00/00/0000' into the column. I believe the value is originating from a PowerBuilder DataWindow update.
The application uses myriad libraries for all sorts of technologies, so this question may be a bit vague, but...
Has anyone seen the date 02/31/2157 in some established library that Oracle could be defaulting to when some other invalid date is entered? Perhaps an end-of-time concept analogous to the beginning-of-time date of 1/1/1970?
From http://download.oracle.com/docs/cd/B19306_01/server.102/b14220/datatype.htm#i1847"
Oracle uses its own internal format to
store dates. Date data is stored in
fixed-length fields of seven bytes
each, corresponding to century, year,
month, day, hour, minute, and second.
2157-256 = 1901, which seems suspiciously close to a possible epoch of 1/1/1900 (or 12/13/1901 - which is the rollover date for the Year 2038 Problem)
I'd guess that it is storing either 0x00 or 0xFF in the date bytes, then getting confused when it decodes it. (How does it deal with month 255?)
Turns out this was a powerbuilder issue. The field was created in the datawindow as required, but was programmatically changed to be non-required before saving. So a null value was being saved to a non-null database column, and powerbuilder inserted some dummy date instead of just throwing an error.
I remember getting a weird value when saving an invalid date. IIRC it was in PB 9 and we had to get an EBF for it. It was a problem with Date Editmasks and entering an invalid date that wasn't rejected. Sorry I don't have more details.

Resources