I have created a database with a String column which contains dates in String format (dd/mm/yyyy). I want to fetch the data from that table which is between two given dates, but when I tried with the below query, I found that it doesn't make any difference what month and year I have selected; it compares the "dd" field only from "dd/mm/yy".
The below query will display all the data which is between day 14 to 25 from every month and year. I want data between the given date, month, and year.
Select * from RunningLog
where CAST(RunDate AS DATETIME) between CAST('14/04/2011' AS DATETIME) and
CAST('25/04/2011' AS DATETIME)
Please see my answer here about how dates are (or are not) stored in sqlite3. Sqlite doesn't have a date field, so its actually stored as a string. Trying to sort / filter on this will prove to be difficult. Instead use an int field, and store the time in milliseconds.
I prefer INTEGER / Unix time storage, then use the built in date and time functions to format when pulling from DB.
Example:
long millis = Calendar.getTimeInMillis();
Store millis in the database as an integer. Then, refer to the first link on how to use the date and time functions in sqlite3.
Sqlite3 documentation does not say it can cast a datetime: http://www.sqlite.org/lang_expr.html (refer to Cast expressions numeral). Why don't you do that from Java? I mean, how are you storing the dates in the database? I highly recommend saving a long (Unix time); that way you can easily get a couple of long numbers that represent an exact date and time and use them to query your table.
Recomendation: Use Datetime fields in the database and JodaTime as a Time library.
Is quite easy to parse the datetime into a DateTime object and then you have many useful methods to compare and work with dates.
Also, your SQL queries will be better.
You can compute the number of seconds between two dates. Here is an example:
SELECT strftime('%s','now') - strftime('%s','2004-01-01 02:34:56');
Based on the sign of the difference you can say if one date is before another. In your case you have to do two comparisons, so you have to verify the sign of two differences. Here you can find other examples, maybe they give you other ideas (http://www.sqlite.org/cvstrac/wiki?p=DateAndTimeFunctions).
Related
What is the proper way to save date or time based data in the database?
What are the proper "field mappings" for java to postgresql(or to some other database)?
That data should be stored in utc format without timezones.
-> timestamp and date based stuff fails in here, those will add current timezone (http://docs.oracle.com/javase/7/docs/api/java/util/Date.html)
-> what are the other options?
should I use "plain epoch/integer" column and other column for timezone? But then I cannot use all the functions etc. that the database is providing for me.
I could use hibernate with some jodatime magic, but in my current stack I don't have hibernate in use.
Possible solutions:
1). Change the computer/java timezone -> java will in the UCT (eg. export TZ="GMT" or -Duser.timezone=UCT)
2). Use epoch/Integer/Long values in date/time fields / types -> works but now I cannot use build in database functions.
3). Use Jodatime with custom hibernate datatypes?
4). Use Java8 new time and date apis?
In most cases, it is best to use the Postgres data type timestamptz (short for timestamp with time zone) when dealing with multiple time zones or when you want to save all timestamps as UTC.
Don't let the name mislead you, the time zone is not actually saved. But (as opposed to timestamp [without time zone]) the time zone from textual input is taken into account as modifier to compute the actual UTC timestamp value, which is saved.
On output, the text representation of the value is formatted according to your current time zone setting: timestamp is shifted and the according time zone modifier attached to it.
Note that timestamps without appended time zone are interpreted according to the current time zone setting of your session. If you want to enter a literal UTC value disregarding the current time zone, it has to be:
'2014-08-21 16:39:09+0'::timestamptz
not:
'2014-08-21 16:39:09'::timestamptz -- would assume current time zone
Detailed explanation in this related answer:
Ignoring timezones altogether in Rails and PostgreSQL
As you say, it would be best to store dates as UTC on the database. In oracle you can use a DATE or TIMESTAMP datatype. You can then use the java layer to present your dates in local time to the user and with a java.sql.timestamp column. Joda is essentially built in to the latest version of java so definitely use that for any conversions etc. The alternative would be to store timestamp with timezone in oracle and perhaps use oracle date functions in your sql and stored procedures to convert the date as required. We do the former, but it may depend on your team (db people vs java people) and your audience - are there likely to be lots of different timezones in the user base or is timing on the DST changeover going to break your app.
If you can describe particular situations you are concerned about I'm sure someone will help out. Storing your data in UTC will at least ensure that your data is solid but may require many conversions in the presentation layer.
There is not a single correct way but I my opinion is that you should store time as a long unix timestamp and single dates as epoch days. Java 8 has nice functions to deal with them. Avoid locking yourself with jodatime and hibernate just to manage a date.
What do you mean functions that the database is providing you?
You can always do SQL selects with integers and long since they are called from your program.
If you need a lot of manual use of the database (not programmatic) then you may want to use human readable dates.
I'm using SQLite to store some data and I am aware that a date object cannot be stored an SQLite database so I'm using a string.
My problem is that I want to check for the earliest date that is the table. So if there are 2 cards one which was 01/04/2013 and 04/05/2013 I want to recognise that 01/04/2013 is the earlier date and return that row.
So far I have come up with 2 solutions:
Multiple queries to the DB
I have been able to implement a successful solution that will iterate through the database and decrease a date object by 1 which is then used as a string to match the date. The issue is that the database may need to be queried 100 times before it finds the earliest date. Is it bad practice to do it this way?
Iterative through the result set
Another possibility is to iterate through a result set of all the flashcards in the table. However, this would involve 2 loops, one to iterate over each row in the table which would be inside a loop that would decrease the date by 1.
I feel that both of these are not great solutions. I wonder if someone could help me achieve this in a more efficient manner?
If you store your dates in YYYY-MM-DD format, you can use <, >, and BETWEEN like you would with actual Date datatypes. With the YYYY-MM-DD date format, the lexicographical order is the same as the chronological order.
An added benefit is that the YYYY-MM-DD date format is compatible with SQLite Date And Time Functions.
Store the date as the number of days since 1 January 1970.
That way, the SQL becomes
Select MIN(days)
I am trying to store Date in sqlite database in android mm/dd/yyyy , I have read about this What happens if I don't have HH:mm:ss (which is not needed for my application)?.
Is avoiding the date format of database by splitting it up a method used in the industry? ex:
Db Columns:
_id INTEGER;
data TEXT;
day INTEGER;
month INTEGER;
year INTEGER;
Thanks for any advice.
You could store the Date in milliseconds. Then build the appropriate format according the user's Locale at run time.
If you wand to use ony little memory, consider to store ddMMyyyy in a single intvariable.
either easy to read in logoutput
day+month*100+year*10000
day, month year can be extracted by devision and modulo operations
or for faster to handle for the computer
day&0x1F+(month<<5)&0xF+(year<<9)
day, month year can be extracted by >> and & and operations
For compatibility reasons, my app stores dates as strings, in ISO "YYYY-MM-DD" format. This is a special case though. For most purposes, Sam is the man.
SQLite's date functions also understand date strings in yyyy-mm-dd format.
Splitting up dates into their three fields is possible, but then you will not be able to easily do computations on them.
So me and my partner have been working on this project for a while now. We work with dates A LOT in this project, and we recently noticed an issue, and we are rather deep in at this point.
We store our times in SQLlite (Android project) as a formatted string, since a lot of the time they are directly bound to listviews and such.
The problem we noticed, which i found kind of odd, is that that SimpleDateTimeFormat object, when used to format to 24h time (its a medical based project, so 24h time is the convention here) 12:00am-12:59am are formatted to 24:00-24:59, instead of 00:00-00:59...
This isn't too much of an issue until we query the database and order the results by the dates, any data that is between 12:00am and 12:59am will show up at the end of the list, but it should show up at the beginning...
Anyone else encountered this problem? or know a way around it? The best thing possible would be a way to store the data as 00:00 not 24:00.
Cheers
I strongly suspect you're using the wrong pattern. We've got to guess as you haven't posted any code (hint, hint), but I suspect you're using a pattern such as
kk:mm:ss
instead of
HH:mm:ss
Sample code:
import java.util.*;
import java.text.*;
public class Test {
public static void main(String[] args) throws Exception {
SimpleDateFormat broken = new SimpleDateFormat("kk:mm:ss");
broken.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));
SimpleDateFormat working = new SimpleDateFormat("HH:mm:ss");
working.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));
Date epoch = new Date(0);
System.out.println(broken.format(epoch));
System.out.println(working.format(epoch));
}
}
Additionally, as others have pointed out, you shouldn't be storing your values in string format to start with... avoid string conversions wherever you can, as each conversion is a potential pain point.
Please read this and this about how SQLite stores dates (or doesn't store dates). SQLite doesn't have a "Date" type, so it is stored as a string. You should store your date as an integer (milliseconds), and then you can use date and time functions to pull them out (from the first link).
From the documentation
1.2 Date and Time Datatype
SQLite does not have a storage class set aside for storing dates
and/or times. Instead, the built-in Date And Time Functions of SQLite
are capable of storing dates and times as TEXT, REAL, or INTEGER
values:
TEXT as ISO8601 strings ("YYYY-MM-DD HH:MM:SS.SSS"). REAL as Julian
day numbers, the number of days since noon in Greenwich on November
24, 4714 B.C. according to the proleptic Gregorian calendar. INTEGER
as Unix Time, the number of seconds since 1970-01-01 00:00:00 UTC.
Applications can chose to store dates and times in any of these
formats and freely convert between formats using the built-in date and
time functions.
I prefer INTEGER / Unix time storage, then use the built in date and time functions to format when pulling from DB.
EDIT: Also, this will take care of sorting. I'm guessing your current "sorting" of the dates in SQLite is string based, which is bad mmmmkay.
What is the format string you are passing to your SimpleDateFormat? According to the docs, using 'H' for the hours should get you 0-23, using 'k' should get you 1-24.
I want to make a database that will hold a date in it(SQLite).
Now first to ask is what is the right syntax to declare a date column.
The second i want to know is how to insert date in it after that.
And the third thing i want to know is how to select dates between, for example to select all rows which contain date between 01/05/2010 and 05/06/2010.
Thank you
Now first to ask is what is the right syntax to declare a date column.
From the SQLite Data Types documentation:
1.2 Date and Time Datatype
SQLite does not have a storage class set aside for storing dates and/or times. Instead, the built-in Date And Time Functions of SQLite are capable of storing dates and times as TEXT, REAL, or INTEGER values:
TEXT as ISO8601 strings ("YYYY-MM-DD HH:MM:SS.SSS").
REAL as Julian day numbers, the number of days since noon in Greenwich on November 24, 4714 B.C. according to the proleptic Gregorian calendar.
INTEGER as Unix Time, the number of seconds since 1970-01-01 00:00:00 UTC.
Applications can chose to store dates and times in any of these formats and freely convert between formats using the built-in date and time functions.
Take your pick. I'd go for TEXT or INTEGER. The INTEGER will be faster. If you need to store dates past 1970 (e.g. birthdates, etc), then I'd go for TEXT. If you just need to store creationtime/modificationtime, etc for now and the future, then go for INTEGER.
The second i want to know is how to insert date in it after that.
Use PreparedStatement#setString() or #setLong() respectively.
And the third thing i want to know is how to select dates between, for example to select all rows which contain date between 01/05/2010 and 05/06/2010.
Use the standard SQL BETWEEN clause for this. You first need to convert the date accordingly using the built-in date and time functions.
A convenient syntax for declaring a date column is like this:
"CREATE TABLE "
+ "my_table"
+ "(date_time "
+ " DATETIME DEFAULT CURRENT_TIMESTAMP);");
This will default inserted values to the current datetime. Or you can use CURRENT_DATE, or CURRENT_TIME values. You won't have to insert a timestamp manually each time you create a row.
You can read about this approach here: Android insert datetime value in SQLite database