What's a good way to implement a date filter in a list where the items have different timezones? - user-interface

We have an app that lists sport events. An event is associated to 2 teams (home team and away team). In the event list, we are showing the date of the event in the home team's timezone. We are storing dates in the database in UTC. We need to add a date filter in the event list page, but the problem is, since we are storing the date in our db in UTC and the dates in the event list is being shown in the home team's timezone, the date filter is showing unexpected results. the date is saved in our db as 2016-02-18 03:30:00+00 (UTC). When shown to the user in the event list it is 02/17/2016 7:30pm because the home team is in Pennsylvania and the timezone is America/New_York.
now when the date filter is set to 02/17/2016 by the user, we are querying the the db to fetch all events where the date is 02/17/2016. It will cause unexpected results since it will not match the event because in our db the date is 02/18/2016.
One solution I can think of is show 2 date & time columns in the event list.
Date (UTC) | Time (UTC) | Date (Home team's timezone) | Time (Home team's timezone)
And inform the user that when using the date filter it will filter the events using date (utc)
But we're currently looking for a better solution. Any help / suggestion would be greatly appreciated :)
EDIT:
event 1:
- date: 01/12/2016
- time: 9:00am
- home team's timezone: America/Chicago
event 2:
- date: 01/12/2016
- time: 9:00am
- home team's timezone: America/Denver
event 3:
- date: 01/12/2016
- time: 9:00am
- home team's timezone: Asia/Singapore
if the user selects 01/12/2016 in the date filter. It should still show the 3 events above.

Add a new field in the database which stores the dates in its local time and use that field to filter the results.
so when you filter say, 2016-04-01, it will actually be filtering things across different timezones i.e. events that are not at the same Epoch time
so show me all events for e.g. Thursday, regardless of where the teams are (meaning that one team’s thursday is another team’s friday)
it will filter results that are localised to wherever the date was stored from.
Another solution is to use on the fly conversion query.
Example:
where convert_to_local_without_timezone(event_datetime, event_tz) = date_filter
It can be a user defined function - http://www.postgresql.org/docs/8.0/static/xfunc.html if there's no existing function that can achieve this.
Credits to:
Aries, Ryan Johnson and Nikki Erwin Ramirez

Related

Laravel WhereDate Filter in Auth User Time zone

My default Laravel application timezone is America/Los_Angeles (pst), I'm storing all the timestamps like created_at with this timezone in database.
In the user profile, we are providing options to select a timezone. While showing the list of data for example in trip listing I'm converting & showing created at as per user selected time zone ( $date->setTimezone($user->timezone);)
For example, if the trip Id 197 has created_at 2020-06-11 23:00:00 stored in db (as per default application timezone i.e. pst) while in the listing I'm showing 2020-06-12 02:00:00 (est timezone as per user profile 3 hrs ahead).
Now everything works fine until I had to add date range (start & end date) filter in the listing. The problem is if I'm selecting start date 2020-10-12 in the filter, in result it is not getting 197 trip id because in the database it is stored as 2020-06-11 23:00:00., this 197 id record should be there in listing after filter because as per auth user timezone the trip is added on 2020-06-12. My DB query is $trips->whereDate('created_at', '>=' ,$request->start_date);. I have the only date and not time in request for filter trips I need to somehow pass timezone in this query or is there any better solution for this. The date filter should work as per user selected timezone
if anyone faced a similar problem following is the answer I found Generally for date range filters you’ll want to make sure you’re setting the start dates time to 00:00 and the end dates time to 23:59
if($request->filled('start_date'))
{
// $request->start_date;
$date = Carbon::parse($request->start_date, auth()->user()->timezone)
->startOfDay()
->setTimezone(config('app.timezone'));
$brokers->where('created_at', '>=' ,$date);
}
if($request->filled('end_date'))
{
$end_date = Carbon::parse($request->end_date, auth()->user()->timezone)
->endOfDay()
->setTimezone(config('app.timezone'));
$brokers->where('created_at', '<=' ,$end_date);
}
When you can have different timezones for 1 column in a table, you need dateTimeTz to store both datetime + timezone for each row.
With this, the whereDate will use the timezone stored, then you can reconvert to any other timezone on need without loss.

MSCRM OlderThanXHours and the current time

I created a QueryExpression with one of the Conditions set to ("dev_lastremarketingtime", ConditionOperator.OlderThanXHours, 1); 
The intent is the retrieve multiple records that are an hour after the value of dev_lastremarketingtime.
There are records in the table that meet this criterion, however, they are not returned. When I examine the record (RetrieveMultiple of a specific record this time) it seems that the times used for comparison are not consistent. 
For example, when viewing the account record in question, the dev_lastremarketingtime's value as shown on the account form is 5/17/2017 8:57 PM. the internal is time 5/18/2017 12:57:27 AM.  The wall clock at the time of the test shows 5/17/2017 10:38:11 PM (or 5/18/2017 2:38:11 AM UTC). This record should have been returned by the query (the current time is more than one hour after the value of dev_lastremarketingtime)
If I wait a few hours and run my app again, the expected records are retrieved.
It seems, therefore, that the Query expression with the ConditionOperator.OlderThanXHours is comparing the current Eastern Daylight time with the record's UTC time. 
How can I get this query to compare the same time zones (I don't think it matters which one)?
(My Personal options include the setting for Eastern Time
Instead of using the OlderThanXHours operator, maybe try using "less than", which provides control of the DateTime value to filter on.
This way you can use the UTC time minus an hour, like this:
var qe = new QueryExpression("myentity");
qe.Criteria.AddCondition("dev_lastremarketingtime", ConditionOperator.LessThan, DateTime.UtcNow.AddHours(-1));

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

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