How to store current locale date and time in SQLite - android

..and later retrieve and show them as Strings?
I'm asking the user some input and I want to store both the date (i.e., day, month and year) and the time (i.e., the hour of the day) this input was submitted. Each submission is then saved in my SQlite database, and later retrieved from a RecyclerView.
I'm facing two problems at least. Right now I set up two TEXT fields in the database, FIELD_DATE and FIELD_TIME, where I'd like to store the string representation of date & time, in a format depending on the Android user locale.
From what I've read, the android.text.format.DateFormat should help me. So I set:
java.text.DateFormat dateFormat = DateFormat.getMediumDateFormat(getActivity());
java.text.DateFormat timeFormat = DateFormat.getTimeFormat(getActivity());
Now I think I should call format(Date d) on both objects to get my string, but I don't know where do I get this Date object - don't even know if my two lines are correct. So:
How to get a string representation of current date & time, based on the user defined (at OS level) locale?
That said (asked), I wonder if two fields for date & time are really what I'm looking for. As said, at the end I would like to show a RecyclerView reading the database. In that I will also need to filter out entries based on date, i.e.
Entries referring to last week // last month // All
entries
So I'm also asking:
Is a two-text-fields pattern the right choice to store date & time, given the need to easily filter out entries belonging to, say, last week? Should I better have separate columns for day, month and year?
How to query the database to have only last week rows, given the FIELD_DATE / FIELD_TIME structure (or any other better structure you can suggest)?
I'm quite stuck on these three questions.
Edit: finally came up with how to get the strings I wanted at first, it was as simple as instantiating a new Date object:
Date d = new Date();
String date = DateFormat.getMediumDateFormat(getActivity()).format(d);
String time = DateFormat.getTimeFormat(getActivity()).format(d);
Now I have both the needs to display these strings (which is quite simple, as they are already formatted) and to apply some filter to the db, like entries belonging to last week (which, in turn, would be quite simple with current time in millis since 1970). What to do?

If you want to be able to run complex queries such as find all records from last week, I would recommend storing a timestamp in an integer instead. A timestamp is expressed as the number of milliseconds since the Epoch (Jan 1, 1970). It makes it easy to make queries on exact date and time ranges.
The timestamp is easily found from e.g. System.currentTimeMillis().
The other approach would be to use sqlite's built in date type, but I would personally choose the timestamp approach.
Is there any reason you would want to store it in the current locale's format in the first place? If you are displaying the date to the user you're likely better of formatting the timestamp into a date when displayed, using one of the many date features of Java and android such as java.util.Calendar, java.util.Date, android.text.SimpleDateFormat etc.
As an example, you could run this code to get the timestamp of the start of this month:
Calendar now = Calendar.getInstance();
now.set(Calendar.DAY_OF_MONTH, 1);
now.set(Calendar.HOUR_OF_DAY, 0);
now.set(Calendar.MINUTE, 0);
now.set(Calendar.SECOND, 0);
long startOfThisMonth = now.getTimeInMillis();

Related

Issue with formatting time zone for Joda DateTime from ISO String

So time formatting and adjusting has always been my biggest nemesis in programing and I'm having some issues in Android/Java that I can't figure out. I get a timestamp from a server that is formatted in UTC (here's an example 2016-06-17T18:30:00-07:00. Now this time needs to get formatted to the users local time (so for a user in PST it should show as 11:30AM) but so far whatever I try I either get 1AM or 6:30PM (so I know I'm doing something wrong I just don't know what). Here's what I've been trying to do
public static DateTime convertISOStringToDate(String inputString) {
//setup the ISO Date Formatter with GMT/UTC format
DateTimeFormatter formatter = ISODateTimeFormat.dateTimeParser()
.withLocale(Locale.US)
.withZone(DateTimeZone.forOffsetHours(0));
DateTime dateTime = formatter.parseDateTime(inputString);
//now convert the datetime object to a local date time object
DateTimeFormatter localFormatter = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")
.withZone(DateTimeZone.getDefault());
String localString = localFormatter.print(dateTime);
DateTime localDateTime = localFormatter.parseDateTime(localString);
return localDateTime;
So at this point I'm getting 1:30AM, so I know I'm messing it up somewhere in the conversion process but I can't figure it out. I've been trying to google around but so far haven't found much that use the ISODateTimeFormat parser so they don't work either when I try them.
You seem to have a basic mis-understanding of how dates are represented.
A date (in almost every known programming language / library) is represented internally as an offset from a specific 'origin time', known as the 'Epoch'.
In java.util.Date as well as joda dates, the internal representation is the number of milliseconds since midnight, Jan 1, 1980, UTC.
As such, a date does not have a timezone. You only introduce a timezone when you format a date (turn it into a String representation of the date).
You have made the common mistake of parsing a String into a date object, serializing (printing) it back out with a different timezone than the the original string indicated, and then parsing back into a date again, expecting something to have changed. If you do that correctly, you will get back exactly the same date that you started with.
In your case, the "localString" that you get shows the correct time in the local timezone. I'm in EDT, which is UTC-4:00, and I correctly get 2016-06-17 21:30:00 as the result.
As I said, parsing that back into a DateTime, and then looking at it is useless, because:
You'll get the same DateTime back that you started with
Your IDE (or whatever you're using to inspect the DateTime) probably isn't showing what you expect.
You should re-evaluate what you're doing here, and whether you really need to "convert" the DateTime, or to just parse it, and really understand how date formatting works with respect to timezones.

Using a DatePicker in Android dev: How do I compare the date picked to today's date?

I'm really stuck with a certain problem and I'm hoping someone can help me understand the problem and come to a solution. I've looked online a fair bit but can't see an answer unless it's been staring me in the face :-/
Basically, I'm creating a very basic TV Guide app. It parses data from an RSS feed which has days offset (yesterday was -1. today is 0, tomorrow is 1, etc etc) and I'm trying to implement a DatePicker that allows the user to see what is on a particular channel when they select yesterday, today, tomorrow, etc.. but if they pick a date that is out-with the range (at the moment it's a week in advance), a simple Toast message will be displayed.
My questions I guess are, firstly, how do I use maybe an IF ELSE to either parse the specific channel data for the day the user wants or display an error Toast message, and, how do I go about converting the days from what the user has put in compared to the actual date today into integers? If they select yesterday's date it will go to URL "http://example.com/-1/channel", if they select tomorrow's date it will go to URL "http://example.com/1/channel" etc etc etc.
Code is available if anyone needs to see it, but I think if someone would be kind enough to explain the logic, I'd like to see if I can come to the answer myself...
Thanks a lot folks!!
You should use a DatePicker to allow the user to choose the when.
Time in Android is stored on a long (not an int). And the long time can easily be converted back and forth between long (always milli-seconds) and a Date object.
The Date object gives you all sorts of tools to compare before and after, look at months, minutes, hours, etc.
The current time is determined by:
long nowMs = System.currentTimeMillis();
int nowSec = (int)(nowMs / 1000);
There is also a very important Calendar object. This allows you to parse textual date formats as delivered by your http functions in and out of various dates.
For example:
Calendar cal = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-mm-dd hh:mm:ss Z");
String text = sdf.format(cal.getTime();
You will have to put all these tools together with a DatePicker example such as the one here Create a DatePicker to complete your TV Guide application.
Reference:
Date
Calendar
DatePicker
EDIT : Check David's Answer its better.
First Filter the date selected with today's date. You can compare it by date.isbefore(date) or date.isafter(date) these booleans will let you tell know if a date is of past or future or present. then to further calculate the days inbetween you can make a method with switch statement that will basically convert the selected date and the current date into miliseconds(Date.getTimeinmiliseconds)
if the date is of past take the difference of present time in miliseconds and past date in miliseconds. If the date is of future do the opposite. Take the difference and convert it to days difference with appropriate sign(negative/positive).
Please refer this link for a better coding example

Android inconsistency when dates are stored as longs and the time zone is changed

I have an Android app that is used by people in the UK and Ireland only, and there are no plans for this app to be used overseas.
In the app I store dates for various things, although I never need the full timestamp including the time of day, I only need the date.
So that I can compare dates easily, I've been creating calendar objects and clearing the values of the time, and using the milliseconds of that to store in the database.
public Calendar clearCalTime(long l) {
Calendar cal = Calendar.getInstance();
cal.setFirstDayOfWeek(Calendar.MONDAY);
cal.setTimeInMillis(l);
cal.clear(Calendar.HOUR);
cal.clear(Calendar.HOUR_OF_DAY);
cal.clear(Calendar.MINUTE);
cal.clear(Calendar.SECOND);
cal.clear(Calendar.MILLISECOND);
return cal;
}
The issue has been that if users change the timezone, for some reason the dates start messing up, e.g by saving things to the wrong day. The timezones could be anything, I have no control over what the users set.
I've tried setting the timezone to UTC but this doesn't work either. Is there any way to just disregard the timezones?
Nope. You are going to have to set TimeZone going in and out of your storage.
You'll need to do this:
Calendar c = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
in your code to make it consistent.
See this SO: Java.util.Calendar - milliseconds since Jan 1, 1970
Alternatively use Joda Time when dealing with complicated Date/Time math.

GregorianCalendar and SQLite

I'm trying to setup a RPG that will keep track of a virtual time. After some reading GregorianCalendar seems to be the best way to do this but I have some questions and hoping someone with experience could give me some insight.
Here is what I'm trying to do. The game will start in the year 1675 and run for about 30 years. At that point the character will retire if they have survived that long. The character will be able to choose from actions I've preset for them through the coarse of the game. Some actions will be short and take a hour, others may take a week or a month. The real question comes from me using SQLite heavily. I want to save the current time as well as how long an action will take in my database. My first thought when setting this up was, if I want to start the game in Aug 15, 1675 to have my data base with 3 rows, set those fields to 8, 15, 1675. Then also have 2 more columns for the time. Pull these int via cursor and set them with something like
GregorianCalendar time = new GregorianCalendar();
time.set(year, month, date, hour, minute);
I figured I would pull how long an action takes in a similar fashion. Have an int X, and then a string to tell whether this time is in minutes, hours, days etc. Then either add this int to the int pulled from database to add to the calendar directly.
Q: If I add it directly to the calendar how would I pull int values from the calendar to store in database to load at a later time (when the player loads their game)?
Q: If I add it to the int stored in the database and set the calendar with this new int what will happen when I add enough to make the int out of scope for the calendar (Date is set to 31 but I add another day)?
You can convert from the GregorianCalendar object to/from UNIX time for example using getTimeInMillis() setTimeInMillis(). GregorianCalendar also has a roll() method:
Adds the specified amount to the specified field and wraps the value
of the field when it goes beyond the maximum or minimum value for the
current date. Other fields will be adjusted as required to maintain a
consistent date.
I would recommend using Joda Time as a substitute for the (somewhat lacking) standard java date and time utilities. It's much more flexible.
It has functions to do date math, it supports several different calendars (ISO8601, Buddhist, Coptic, Ethiopic, Gregorian, GregorianJulian, Islamic, Julian), has support for intervals, durations and periods. It has built in formatters that let you make your output look like just about anything you wish.
If it were me, I would use Joda and store the date in the native format presented by Joda (I don;t remember what that is right offhand) and then pull it out again and use Joda to do all the date math, as well as having it convert it to whatever calendar you wish to use for display to the user.
Otherwise, it seems to me you'd be re-inventing the wheel.

Outputting specific rows from SQL database using Date format

I'm writing an application where users enter some details into an SQLite Database. I need to write code whereby the last 31 days of stored data in the database is outputted.
The code to save the date string is:
currentDateString = DateFormat.getDateInstance().format(new Date());
This gives the date in the format (for todays date) as 30 Mar 2012.
Is there anyway to change this data format into DD/MM/YYYY? (30/03/2012)
This string is saved into the SQL Database as follows:
ContentValues dbcv = new ContentValues();
dbcv.put(KEY_DATE, date);
(currentDateTime String = Date in previous class)
I wish to output every row of the database that comes within the last 31 days.
How can I do this?
Thanks!
First of all, you are doing two questions instead on just one, I will try to give you an answer to both.
To change the date format in java take a look at the documentation for the SimpleDateFormat, you can pass a pattern to the constructor of that class to make it format your dates the way you really want. In your specific case the pattern you are looking for is dd/MM/yyyy
If you are storing dates in your database as strings you lose some of the benefits that storing dates as they are have. For example, your second question will be easily performed if you were storing dates instead of strings in your tables since the only thing you need to achieve what you want is to do a select operation to your table using the date functions provided by SQLLite. Take a look a this webpage as it will give you an idea of what you can do with those functions: SQLLite Date Functions
Note: Of course, if you still want to store them as strings the only solution you will have is read all the records, parse all the strings back to dates and use the java.util.Calendar class to check which record is older than 31 days and which one is not. I'd rather do the SQL query instead of that as it has too much better performance (specially on a mobile device).
EDIT:
SQLLite and Android are not specifically my strengths, I did a small research and I found several posts in which people were actually storing them as strings as you initially started to do. If SQLLite on Android doesn't support storing dates as they are (as other databases do) then maybe the best option in your scenario is using a long value as the date. Look at the Date definition class, it has a method getTime that returns the date value as long value, you can use that value later to create a new instance of a date (using its constructor).
To format that date (the Date object, of course) in something readable by the user, DateFormat (or any of its implementations) is still the answer.
To do the query you want to do having dates stored as longs I suggest you to take a look to the DateUtils class from the Apache Commons Lang library. In that class you will find several functions that work on dates, so, before creating the query you need to fetch the rows in last 31 dates, you could use something like:
Date now = new Date();
Date before = DateUtils.addDays(now, -31);
long beforeAsLong = before.getTime();
String query = "select * from TABLE_NAME where DATE_FIELD >= " + beforeAsLong;
Hope this helps.

Categories

Resources