Date comparison Sqlite Android - android

How do I make a comparison between dates using SQlite, I tried this more failed. help: D
My Query:
SELECT
latitude,
longitude,
grupo_crime_id_grupo_crime,
descricao,
id_crime,
cities_id_cities,
time,
estado
FROM crime WHERE
cities_id_cities='0' AND
time >= datetime('2013-03-28T09:30:37-03:00')
time <= datetime('2013-0328T09:30:37-03:00') AND
grupo_crime_id_grupo_crime='1'

use like this:
select * from MyTable
where mydate >= Datetime('2000-01-01 00:00:00')
and mydate <= Datetime('2050-01-01 23:00:59')

Related

How do I get certain row in ROOM Database by month and year

I have a table where I put Date as long and when I convert it back to String it would be "dd/mm/yyyy". I want to fetch certain data with month and year, so the custom query would be like :
SELECT id FROM things
WHERE MONTH(happened_at) = 1 AND YEAR(happened_at) = 2009;
the example table has data like this :
id happend_at
-- ----------------
1 2009-01-01 12:08
2 2009-02-01 12:00
3 2009-01-12 09:40
4 2009-01-29 17:55
I'd like to know how to fetch data like that where the happened_at is in long and not String like the example above.
I'm currently learning to make android app using java and room database, so I made a converter to convert Date into long. The converter is like this :
import androidx.room.TypeConverter;
import java.util.Date;
public class DateConverter {
#TypeConverter
public static Date fromTimestamp(Long value)
{ return value == null ? null :
new Date(value);
}
#TypeConverter
public static Long dateToTimestamp(Date date)
{
return date == null ? null :
date.getTime();
}
}
Try using :-
SELECT id FROM things WHERE CAST(strftime('%m',happened_at / 1000,'unixepoch') AS INTEGER) = 1 AND CAST(strftime('%Y',happened_at / 1000,'unixepoch') as INTEGER) = 2009;
This works because:-
the value will be stored as a value that includes the milliseconds according to the TypeConverter as per
The getTime() method of Java Date class returns the number of milliseconds since January 1, 1970, 00:00:00 GTM which is represented by Date object.
Dividing by 1000 strips the milliseconds which is then a Unix_Time values (seconds since 00:00:00 on 1st Jan 1970).
strftime is SQLite's date/time function and can be used for conversion/formatting dates from the recognised types (see link section 2)
The unix_epoch modifier, lets the SQLite strftime function discern between numbers being either Julian Day (without 'unixepoch' modifer) or Unix Time values (with the modifier).
'%m' retrieves the month as a string padded with preceding 0's to always be 2 characters, '%Y' for the year part.
see https://www.sqlite.org/lang_datefunc.html
The CAST expression strips preceding 0's from the result should they exist i.e. converts 01 to 1.
an alternative to using CAST could be to force an integer (rather than string) value, say by adding 0 e.g. SELECT id FROM things WHERE 0 + strftime('%m',happened_at / 1000,'unixepoch') = 1 AND 0 + strftime('%Y',happened_at / 1000,'unixepoch') = 2009;

Search period, given current week and year

I have a sqlite table, which has the following columns:
id | description | startYear | startWeek | endYear | endWeek
startYear, startWeek, endYear and endWeek are all integer
So given current week and year (for example week 4, year 2017), how do I search for rows that have startYear, startWeek and endYear, endWeek that include the given week and year?
I'm currently trying to doing this manually by UNION-ing several select query, but I think it's inefficient, and not too mention too much codes (relatively, if there's some sort of built-in query to do this).
My query currently look something like this:
Select id, description
from myTable
where (:currentYear = startYear AND
(:currentWeek >= startWeek OR
:currentWeek <= endWeek ))
UNION
Select id, description
from myTable
where (:currentYear > startYear AND
:currentWeek <= endWeek )
UNION
Select id, description
from myTable
where (:currentYear < endYear AND
:currentWeek <= 53 )
UNION
Select id, description
from myTable
where (:currentYear < endYear AND
:currentWeek <= 53 )
UNION
Select id, description
from myTable
where (:currentYear < endYear AND
:currentWeek <= 53 )
UNION
Select id, description
from myTable
where (:currentYear = endYear AND
:currentWeek <= endWeek);
When you have a query of the form:
SELECT ... WHERE A
UNION
SELECT ... WHERE B
you can trivially transform it into a single query of the form:
SELECT ... WHERE A OR B
The WHERE condition might then be further simplified by using the rules of the Boolean algebra.
But your current query is wrong, so it's better to construct a new one from scratch.
What you want is the equivalent of this:
SELECT ... WHERE currentTime BETWEEN startTime AND endTime;
Now, instead of splitting the time comparisons into the two fields, it would be easier to construct a single time value. Just multiplying the year by 100 and summing it with the week gives a value like 201704, which compares correctly with any other such values:
SELECT ...
WHERE :currentYear * 100 + :currentWeek
BETWEEN startYear * 100 + startWeek
AND endYear * 100 + endWeek;

Entity Framework: How to calculate the range of dates from other date range

I am using an entity framework to calculate how many days from a date range with the target date range.
Let say I passed in a from date A to date B. In each row of the date I have previous log date and current log date. I want to see how many days was sitting inside between the previous log date and current log date.
My code i was currently written is:
var days = toDate.Subtract(fromDate).TotalDays;
var usageLog = (from usageLogs in context.UsageLogs
where
(usageLogs.PreviousLogDate != null
&& (DbFunctions.TruncateTime(usageLogs.CurrentServerLogDate) >= fromDate.Date && DbFunctions.TruncateTime(usageLogs.PreviousLogDate) <= toDate.Date)) ||
(usageLogs.PreviousLogDate == null
&& ((DbFunctions.TruncateTime(usageLogs.CurrentServerLogDate) >= toDate.Date) && (DbFunctions.TruncateTime(usageLogs.CurrentServerLogDate) >= fromDate.Date)))
select new
{
PackageName = usageLogs.PackageName,
estimateUsageCount = (double)usageLogs.UsageCount
});
var statistics = (from usage in usageLog
group usage
by new
{
usage.PackageName
}
into grp
select new
{
PackageName = grp.Key.PackageName,
UsageCount = grp.Sum(c => c.estimateUsageCount)
});
return statistics.ToList();
}
estimateUsageCount in the select statement is where I want to calculate the number of days sitting in between the previous and current log dates.
I am thinking to write function to do the job but don't know how to do it. I know the calculation is quite complicated. Does anyone give me an idea of how to do it.
You can do it like this:
select new
{
PackageName = usageLogs.PackageName,
estimateUsageCount = (usageLogs.CurrentServerLogs - usageLogs.PreviousServerLogs).Days
});
For the range between two dates, I found this excel formula:
=MAX(0,NETWORKDAYS(MAX(Date1, Date2),MIN(dateA,dateA)))
that it can be translated into c# like this, using the ternary operator:
0 > ((date1 > date2 ? date1 : date2) - (dateA < dateB ? dateA : dateB)).Days ? 0 : ((date1 > date2 ? date1 : date2) - (dateA < dateB ? dateA : dateB)).Days

Query in android sql-lite to find the entries made in between two dates which are saved as year, month and day

In a database I have saved the date in form of 3 columns: Year, Month, Day_of_Month
( I know it might not be a best way to save the date but I make certain other queries for which this format felt suitable.)
Now I wish to get all the rows where the date is in between two specified dates. I went through previous stackoverflow questions, but most of them have saved the date as a single entity.
This is how I tried:
I have a MySqLiteHelper class with all the column names declared. I also create the table there. COLUMN_DATE_YEAR, COLUMN_DATE_MONTH and COLUMN_DATE_DAY are the string storing the column names.
int fyear, fmonth, fday; // I populate those initial date values
int tyear, tmonth, tday; // I populate those target date values
String selection = MySQLiteHelper.COLUMN_DATE_YEAR + " >= '"+fyear+"' AND "+ MySQLiteHelper.COLUMN_DATE_DAY + " >= '"+fday+"' AND "
+ MySQLiteHelper.COLUMN_DATE_MONTH + " >= '"+fmonth+"' AND " + MySQLiteHelper.COLUMN_DATE_YEAR + " <= '"+tyear+"' AND "
+ MySQLiteHelper.COLUMN_DATE_DAY + " <= '"+ tday+"' AND "+ MySQLiteHelper.COLUMN_DATE_MONTH + " <= '"+tmonth+"'";
String []column = {MySQLiteHelper.COLUMN_MOOD_LEVEL};
Cursor cursor = database.query(MySQLiteHelper.TABLE_NAMES, column, selection, null, null, null, null);
Now the problem with this approach is that it will give no results for the query between 25 Feb 2013 and 17 March 2013 as the date 25th > 17th, even though the month 2 < 3. This might require some kind of nested where clause. However I am unable to form a nested 'Where' using '.query' method.
Please suggest a way to query for the entries stored in between these two dates. Thanks in advance.
There's no reason why you shouldn't be able to run a somewhat more complex WHERE clause, as follows (for date >= 2013-02-17):
( YEAR > 2013 OR ( YEAR = 2013 AND ( MONTH > 2 OR ( MONTH = 2 AND DAY >= 17 ) ) ) )
This will work, but it's for from optimal. You'd be better off correcting your database design.
Correction: You must fix your database design. Either store the date as DATE type or as ISO string: yyyy-mm-dd.
Bonus: Say you have the following right now:
CREATE TABLE theTable(
....
THEYEAR TEXT,
THEMONTH TEXT,
THEDAY TEXT );
To convert the date to a usable format, you can simply run the following:
ALTER TABLE theTable
ADD COLUMN THEDATE TEXT;
UPDATE theTable
SET THEDATE = THEYEAR || substr( '0' || '-' || THEMONTH, -2, 2 ) || '-' || substr( '0' || THEDAY, -2, 2 );
Once you've done that, you can then query using the BETWEEN clause.
Using your current schema, try reordering your WHERE clause. You need to compare the largest columns first, i.e. year, month, day. With your current year, day, month you cannot accurately compare dates that cross over into new months.
For example: day >= 25 and day <= 17 creates an invalid range. It doesn't account for the correct range: >25, wrap to 1, then <17...
Without changing the table structure the below query will work for you, try it
select * from TableName WHERE (10000*ColumnYear+100*ColumnMonth+ColumnDay >= 20131009) and (10000*ColumnYear+100*ColumnMonth+ColumnDay <= 20131121);

Why does datetime('now') return 2 hours before real time in SQLite?

I need that every time I make a change to a certain record from a table in SQLite, in the column lastChangedDate to set the time from France. Here is the structure of my table :
CREATE TABLE name(
id VARCHAR(36) PRIMARY KEY
, pos_report_id VARCHAR(36)
, path_name VARCHAR(64)
, photo_name VARCHAR(64)
, from_scratch INTEGER DEFAULT 0
, lastChangedDate DATETIME DEFAULT (DATETIME('now', 'utc', '1 hours'))
)
I see that DATETIME('now') returns 2 hours before my real time and DATETIME('now', 'utc', '1 hours') returns with 3 hours before my time. Why is happening this? I need the application to work in more countries, so I cannot use localtime.
Any idea how to solve this?
I have the same problem (using sqlite on Raspbarry Pi). 'utc' obviously only calcultes the difference according to location and timezone. I got it running like this:
select datetime(datetime('now', 'localtime'), 'utc');
Also check out the other variation of my VIEW [NOW] for sensor logging purpose.
CREATE VIEW [NOW] AS
SELECT datetime('now', 'localtime') as LOCAL,
datetime(datetime('now', 'localtime'),'utc') as UTC,
substr(datetime('now', 'localtime'),1,17)||'00' as TimeSlot_1min,
substr(datetime('now', 'localtime'),1,15)||'0:00' as TimeSlot_10min,
substr(datetime('now', 'localtime'),1,14)||'00:00' as TimeSlot_1h;
try datetime('now','localtime') instead of DATETIME('now', 'utc', '1 hours')
Ok dont use default time for lastChangedDate
CREATE TABLE name(
id VARCHAR(36) PRIMARY KEY
, pos_report_id VARCHAR(36)
, path_name VARCHAR(64)
, photo_name VARCHAR(64)
, from_scratch INTEGER DEFAULT 0
, lastChangedDate DATETIME)
)
then when you want to add record to table, you can calculate the time in France and add this value to your database
//Calendar cal = Calendar.getInstance();
//Log.v("hata",String.valueOf(cal.get(Calendar.HOUR)));
Calendar c = Calendar.getInstance();
// It is local time
Log.v("time",String.valueOf(c.getTime()));
TimeZone z = c.getTimeZone();
int offset = z.getRawOffset();
if(z.inDaylightTime(new Date())){
offset = offset + z.getDSTSavings();
}
// france is GMT2
int offsetHrs = offset / 1000 / 60 / 60;
int offsetMins = offset / 1000 / 60 % 60;
// Offsets
Log.v("time",String.valueOf(offsetHrs));
Log.v("time",String.valueOf(offsetMins));
c.add(Calendar.HOUR_OF_DAY, (-offsetHrs));
c.add(Calendar.MINUTE, (-offsetMins));
// FRANCE time
Log.v("time",String.valueOf(c.getTime()));

Categories

Resources