How to insert date in sqlite through java - java

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

Related

How to test for dates earlier than the current date in SQLite

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)

Designing SQLite Database without Date format

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.

How do I know the offset of a time zone from GMT by using its id in joda?

I have a MySQL database in which one column is of type DATETIME and stores the values in IST (as my server time zone is IST).
I am getting a two string in EST from the user for which I need to match the date part in my database with that column.
I am using this query :
SELECT * FROM my_table where date(convert_tz(`myDate`,'+05:30','-05:00'))
between '2012-12-01' and '2012-12-02';
Note: That in my database mysql.time_zone is empty meaning I cannot use strings likeGMTetc in my query, they instructed me to download a package, but I don't want to download it, its fine for me to use00:05` as I will be framing my query in Java.
This query runs fine as I have hardcoded the the time zone offset (for EST.
But I am worried that this query will give wrong data for the dates that fall in Daylight timings i.e. for EDT.
So how do I get the time zone difference (meaning it should return '-05:00' for EST and '-04:00 for EDT ) so that I can directly use them when building my query string in java.
My query string may look like :
SELECT * FROM my_table where date(convert_tz(`myDate`,'+05:30','???'))
between '2012-12-01' and '2012-12-02';
where I want the value at ??? to be dynamically allocated using a prepared statement.
I am using Joda Time API, but don't have much knowledge of it, whether it has something that can return me the timezone offser for a given timezone string.
I would suggest that:
You start storing your values as UTC, for the sake of sanity. (The data shouldn't depend on the server's location.)
You compute the UTC value for the start/end points within Java (using a DateTime set in the right time zone, and then converting to UTC)
You pass the UTC start/end directly into the query via SQL parameters (don't include the values in the SQL text) and avoid the database doing any conversion
If you really, really can't change the database to use UTC instead, you should convert your "target timezone" values into IST values instead, and pass those to the database. Again, the query doesn't need to do conversion: convert your inputs beforehand instead.

Sqlite Query is not working properly

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

How do you store Date ranges, which are actually timestamps

Java & Oracle both have a timestamp type called Date. Developers tend to manipulate these as if they were calendar dates, which I've seen cause nasty one-off bugs.
For a basic date quantity you can simply chop off the time portion upon input, i.e., reduce the precision. But if you do that with a date range, (e.g.: 9/29-9/30), the difference between these two values is 1 day, rather than 2. Also, range comparisons require either 1) a truncate operation: start < trunc(now) <= end, or 2) arithmetic: start < now < (end + 24hrs). Not horrible, but not DRY.
An alternative is to use true timestamps: 9/29 00:00:00 - 10/1 00:00:00. (midnight-to-midnight, so does not include any part of Oct). Now durations are intrinsically correct, and range comparisons are simpler: start <= now < end. Certainly cleaner for internal processing, however end dates do need to be converted upon initial input (+1), and for output (-1), presuming a calendar date metaphor at the user level.
How do you handle date ranges on your project? Are there other alternatives? I am particularly interested in how you handle this on both the Java and the Oracle sides of the equation.
Here's how we do it.
Use timestamps.
Use Half-open intervals for comparison: start <= now < end.
Ignore the whiners who insist that BETWEEN is somehow essential to successful SQL.
With this a series of date ranges is really easy to audit. The database value for 9/30 to 10/1 encompass one day (9/30). The next interval's start must equal the previous interval's end. That interval[n-1].end == interval[n].start rule is handy for audit.
When you display, if you want, you can display the formatted start and end-1. Turns out, you can educate people to understand that the "end" is actually the first day the rule is no longer true. So "9/30 to 10/1" means "valid starting 9/30, no longer valid starting 10/1".
Oracle has the TIMESTAMP datatype. It stores the year, month, and day of the DATE datatype, plus hour, minute, second and fractional second values.
Here is a thread on asktom.oracle.com about date arithmetic.
I second what S.Lott explained. We have a product suite which makes extensive use of date time ranges and it has been one of our lessons-learned to work with ranges like that. By the way, we call the end date exclusive end date if it is not part of the range anymore (IOW, a half open interval). In contrast, it is an inclusive end date if it counts as part of the range which only makes sense if there is no time portion.
Users typically expect input/output of inclusive date ranges. At any rate, convert user input as soon as possible to exclusive end date ranges, and convert any date range as late as possible when it has to be shown to the user.
On the database, always store exclusive end date ranges. If there is legacy data with inclusive end date ranges, either migrate them on the DB if possible or convert to exclusive end date range as soon as possible when the data is read.
I use Oracle's date data type and educate developers on the issue of time components affecting boundary conditions.
A database constraint will also prevent the accidental specification of a time component in a column that should have none and also tells the optimizer that none of the values have a time component.
For example, the constraint CHECK (MY_DATE=TRUNC(MY_DATE)) prevents a value with a time other than 00:00:00 being placed into the my_date column, and also allows Oracle to infer that a predicate such as MY_DATE = TO_DATE('2008-09-12 15:00:00') will never be true, and hence no rows will be returned from the table because it can be expanded to:
MY_DATE = TO_DATE('2008-09-12 15:00:00') AND
TO_DATE('2008-09-12 15:00:00') = TRUNC(TO_DATE('2008-09-12 15:00:00'))
This is automatically false of course.
Although it is sometimes tempting to store dates as numbers such as 20080915 this can cause query optimization problems. For example, how many legal values are there between 20,071,231 and 20,070,101? How about between the dates 31-Dec-2007 abnd 01-Jan-2008? It also allows illegal values to be entered, such as 20070100.
So, if you have dates without time components then defining a range becomes easy:
select ...
from ...
where my_date Between date '2008-01-01' and date '2008-01-05'
When there is a time component you can do one of the following:
select ...
from ...
where my_date >= date '2008-01-01' and
my_date < date '2008-01-06'
or
select ...
from ...
where my_date Between date '2008-01-01'
and date '2008-01-05'-(1/24/60/60)
Note the use of (1/24/60/60) instead of a magic number. It's pretty common in Oracle to perform date arithmetic by adding defined fractions of a day ... 3/24 for three hours, 27/24/60 for 27 minutes. Oracle math of this type is exact and doesn't suffer rounding errors, so:
select 27/24/60 from dual;
... gives 0.01875, not 0.01874999999999 or whatever.
I don't see the Interval datatypes posted yet.
Oracle also has datatypes for your exact scenario. There are INTERVAL YEAR TO MONTH and INTERVAL DAY TO SECOND datatypes in Oracle as well.
From the 10gR2 docs.
INTERVAL YEAR TO MONTH stores a period
of time using the YEAR and MONTH
datetime fields. This datatype is
useful for representing the difference
between two datetime values when only
the year and month values are
significant.
INTERVAL YEAR [(year_precision)] TO
MONTH
where year_precision is the number of
digits in the YEAR datetime field. The
default value of year_precision is 2.
INTERVAL DAY TO SECOND Datatype
INTERVAL DAY TO SECOND stores a period
of time in terms of days, hours,
minutes, and seconds. This datatype is
useful for representing the precise
difference between two datetime
values.
Specify this datatype as follows:
INTERVAL DAY [(day_precision)] TO
SECOND
[(fractional_seconds_precision)]
where
day_precision is the number of digits
in the DAY datetime field. Accepted
values are 0 to 9. The default is 2.
fractional_seconds_precision is the
number of digits in the fractional
part of the SECOND datetime field.
Accepted values are 0 to 9. The
default is 6.
You have a great deal of flexibility
when specifying interval values as
literals. Please refer to "Interval
Literals" for detailed information on
specify interval values as literals.
Also see "Datetime and Interval
Examples" for an example using
intervals.
Based on my experiences, there are four main ways to do it:
1) Convert the date to an epoch integer (seconds since 1st Jan 1970) and store it in the database as an integer.
2) Convert the date to a YYYYMMDDHHMMSS integer and store it in the database as an integer.
3) Store it as a date
4) Store it as a string
I've always stuck with 1 and 2, because it enables you to perform quick and simple arithmetic with the date and not rely on the underlying database functionality.
Based upon your first sentence, you're stumbling upon one of the hidden "features" (i.e. bugs) of Java: java.util.Date should have been immutable but it ain't. (Java 7 promises to fix this with a new date/time API.) Almost every enterprise app counts on various temporal patterns, and at some point you will need to do arithmetic on date and time.
Ideally, you could use Joda time, which is used by Google Calendar. If you can't do this, I guess an API that consists of a wrapper around java.util.Date with computational methods similar to Grails/Rails, and of a range of your wrapper (i.e. an ordered pair indicating the start and end of a time period) will be sufficient.
On my current project (an HR timekeeping application) we try to normalize all our Dates to the same timezone for both Oracle and Java. Fortunately, our localization requirements are lightweight (= 1 timezone is enough). When a persistent object doesn't need finer precision than a day, we use the timestamp as of midnight. I would go further and insist upon throwing away the extra milli-seconds to the coarsest granularity that a persistent object can tolerate (it will make your processing simpler).
All dates can be unambiguously stored as GMT timestamps (i.e. no timezone or daylight saving headaches) by storing the result of getTime() as a long integer.
In cases where day, week, month, etc. manipulations are needed in database queries, and when query performance is paramount, the timestamps (normalized to a higher granularity than milliseconds) can be linked to a date breakdown table that has columns for the day, week, month, etc. values so that costly date/time functions don't have to be used in queries.
Alan is right- Joda time is great. java.util.Date and Calendar are just a shame.
If you need timestamps use the oracle date type with the time, name the column with some kind of suffix like _tmst. When you read the data into java get it into a joda time DateTime object. to make sure the timezone is right consider that there are specific data types in oracle that will store the timestamps with the timezone. Or you can create another column in the table to store the timezone ID. Values for the timezone ID should be standard full name ID for Timezones see http://java.sun.com/j2se/1.4.2/docs/api/java/util/TimeZone.html#getTimeZone%28java.lang.String%29 . If you use another column for the TZ dta then when you read the data into java use DateTime object but set the timezone on the DateTime object using the .withZoneRetainFields to set the timezone.
If you only need the date data (no timestamp) then use the date type in the database with no time. again name it well. in this case use DateMidnight object from jodatime.
bottom line: leverage the type system of the database and the language you are using. Learn them and reap the benefits of having expressive api and language syntax to deal with your problem.
UPDATE: The Joda-Time project is now in maintenance mode. Its team advises migration to the java.time classes built into Java.
Joda-Time
Joda-Time offers 3 classes for representing a span of time: Interval, Duration, and Period.
The ISO 8601 standard specifies how to format strings representing a Duration and an Interval. Joda-Time both parses and generates such strings.
Time zone is a crucial consideration. Your database should be storing its date-time values in UTC. But your business logic may need to consider time zones. The beginning of a "day" depends on time zone. By the way, use proper time zone names rather than 3 or 4 letter codes.
The correct answer by S.Lott wisely advises to use Half-Open logic, as that usually works best for date-time work. The beginning of a span of time is inclusive while the ending is exclusive. Joda-Time uses half-open logic in its methods.
DateTimeZone timeZone_NewYork = DateTimeZone.forID( "America/New_York" );
DateTime start = new DateTime( 2014, 9, 29, 15, 16, 17, timeZone_NewYork );
DateTime stop = new DateTime( 2014, 9, 30, 1, 2, 3, timeZone_NewYork );
int daysBetween = Days.daysBetween( start, stop ).getDays();
Period period = new Period( start, stop );
Interval interval = new Interval( start, stop );
Interval intervalWholeDays = new Interval( start.withTimeAtStartOfDay(), stop.plusDays( 1 ).withTimeAtStartOfDay() );
DateTime lateNight29th = new DateTime( 2014, 9, 29, 23, 0, 0, timeZone_NewYork );
boolean containsLateNight29th = interval.contains( lateNight29th );
Dump to console…
System.out.println( "start: " + start );
System.out.println( "stop: " + stop );
System.out.println( "daysBetween: " + daysBetween );
System.out.println( "period: " + period ); // Uses format: PnYnMnDTnHnMnS
System.out.println( "interval: " + interval );
System.out.println( "intervalWholeDays: " + intervalWholeDays );
System.out.println( "lateNight29th: " + lateNight29th );
System.out.println( "containsLateNight29th: " + containsLateNight29th );
When run…
start: 2014-09-29T15:16:17.000-04:00
stop: 2014-09-30T01:02:03.000-04:00
daysBetween: 0
period: PT9H45M46S
interval: 2014-09-29T15:16:17.000-04:00/2014-09-30T01:02:03.000-04:00
intervalWholeDays: 2014-09-29T00:00:00.000-04:00/2014-10-01T00:00:00.000-04:00
lateNight29th: 2014-09-29T23:00:00.000-04:00
containsLateNight29th: true
Im storing all dates in milliseconds. I do not use timestamps/datetime fields at all.
So, i have to manipulate it as longs. It means i do not use 'before', 'after', 'now' keywords in my sql queries.

Categories

Resources