I want to query SQLite table and get records where the time field (which is a String representing long time in millis) is in the range of tomorrow from querying time.
I also have a field which holds the record date time like this:
dd/MM/yyyy, HH:mm:ss
How would you recommend implementing this?
As per your comment you are open to modify the schema for better performance. So it is better to save time as long (unix timestamp) in database and having an index on that. Once that is done you can simply get tomorrows date at 00:00 in local time zone and convert it to unix timestamp and query based on that. Here is how you can get tomorrows timestamp at 00:00,
public static long getTimeStampAt0000(long timestamp) {
Calendar givenDate = Calendar.getInstance();
givenDate.setTimeInMillis(timestamp);
givenDate.set(Calendar.HOUR_OF_DAY, 0);
givenDate.set(Calendar.MINUTE, 0);
givenDate.set(Calendar.SECOND, 0);
givenDate.set(Calendar.MILLISECOND, 0);
return givenDate.getTimeInMillis();
}
public static long getTimeStampAt0000ForTomorrow() {
long now = System.currentTimeMillis();
long nowAt0000 = getTimeStampAt0000(now);
if (now == nowAt0000) {
// if being queried at 00:00, we are assuming we want same or else we can just remove
// this condition
return nowAt0000;
} else {
return nowAt0000 + 86400000;
}
}
The SQLite doc says that it stores as:
INTEGER as Unix Time, the number of seconds since 1970-01-01 00:00:00 UTC.
Are you certain you have milliseconds since epoch or seconds?
The bundled java.util.Date and Calendar classes are notoriously troublesome. Avoid them. Use either Joda-Time or the new java.time.* package in Java 8.
Note that both java.util.Date and Joda-Time DateTime use milliseconds since epoch, while the new java.time uses nanoseconds. Multiply by 1000L as needed.
When talking about "today" and "tomorrow" with a date-time, you must specify a time zone. The beginning and ending of a day depends on time zone.
// Simulate input.
long millis = DateTime.now().getMillis();
// Use a proper time zone name rather than 3-letter codes.
DateTimeZone timeZone = DateTimeZone.forID( "Asia/Kolkata" ); // Formerly known as Calcutta, India.
DateTime dateTime = new DateTime( millis, timeZone );
DateTime aDayLater = dateTime.plusDays( 1 );
// "Tomorrow" is a span of time.
DateTime startOfToday = new DateTime( timeZone ).withTimeAtStartOfDay();
// Interval comparison is done in "half-open" approach where beginning is inclusive and ending is exclusive.
Interval tomorrow = new Interval( startOfToday.plusDays( 1 ), startOfToday.plusDays( 2 ) );
boolean isDateTimeOccurringTomorrow = tomorrow.contains( dateTime );
boolean isADayLaterOccurringTomorrow = tomorrow.contains( aDayLater );
Dump to console…
System.out.println( "millis: " + millis );
System.out.println( "dateTime: " + dateTime );
System.out.println( "aDayLater: " + aDayLater );
System.out.println( "startOfToday: " + startOfToday );
System.out.println( "tomorrow: " + tomorrow );
System.out.println( "isDateTimeOccurringTomorrow: " + isDateTimeOccurringTomorrow );
System.out.println( "isADayLaterOccurringTomorrow: " + isADayLaterOccurringTomorrow );
When run…
millis: 1392883763016
dateTime: 2014-02-20T13:39:23.016+05:30
aDayLater: 2014-02-21T13:39:23.016+05:30
startOfToday: 2014-02-20T00:00:00.000+05:30
tomorrow: 2014-02-21T00:00:00.000+05:30/2014-02-22T00:00:00.000+05:30
isDateTimeOccurringTomorrow: false
isADayLaterOccurringTomorrow: true
Related
I'm trying to create a simple Alarm Clock, but I stumbled upon a problem that I can't seem to fix. I'm trying to parse a string to a date so I can get the difference between the current time and the time to set off the alarm.
Here's my code to parse the time:
SimpleDateFormat sdf = new SimpleDateFormat("hh:mm:ss");
sdf.setTimeZone(getTimezone());
Date date = sdf.parse(args[0]);
Here's my getTimezone() method:
public static TimeZone getTimezone() {
Calendar cal = Calendar.getInstance();
long milliDiff = cal.get(Calendar.ZONE_OFFSET);
String [] ids = TimeZone.getAvailableIDs();
String name = null;
for (String id : ids) {
TimeZone tz = TimeZone.getTimeZone(id);
if (tz.getRawOffset() == milliDiff) {
// Found a match.
name = id;
break;
}
}
return TimeZone.getTimeZone(name);
}
And here's my code for figuring out the difference:
long diff = date.getTime() - System.currentTimeMillis();
So my problem is that the date.getTime() returns 79680000, while System.currentTimeMillis() returns 1473538047978 (This is of course different every time, but for some odd reason, date.getTime() is not).
Which means that I get a negative number when trying to figure out the difference, and therefore I cannot use it.
EDIT: After a little bit of debugging, I realised that it has to do with the year, month and day not being set, however I do not know how to get those.
You did notice that date.getTime() returns 79680000 which is 22 hours and 20 minutes after 1 January 1970. The problem is (as you noticed) that you did not parse year, month and day.
You can do it by:
SimpleDateFormat sdf = new SimpleDateFormat("DD/MM/YYYY hh:mm:ss");
Example input 20/04/2016 20:20:0 returns time as Mon Jan 04 20:20:00 CET 2016 (don't look at the timezone). It is 1451935200000 miliseconds after 1 January 1970.
Note: change string to match your format requirements (the syntax is self-explanatory).
The accepted answer by Ronin is correct. You are trying to put a time-of-day value into a date-time type.
java.time
Also, you are using troublesome old legacy date-time classes. Now supplanted by the java.time classes.
For a time-of-day value without a date and without a time zone, use LocalTime.
LocalTime alarmTime = LocalTime.parse( "12:34" );
Getting current time-of-day requires a time zone.
ZoneId z = ZoneId.of( "America/Montreal" );
LocalTime now = LocalTime.now( z );
But since we are setting an alarm, we care about the date too.
ZonedDateTime now = ZonedDateTime.now( z );
ZonedDateTime alarm = null;
if ( now.toLocalTime().isBefore( alarmTime ) ) {
alarm = ZonedDateTime.of( now.toLocalDate() , alarmTime , z );
} else {. // Else too late for today, so set alarm for tomorrow.
alarm = ZonedDateTime.of( now.toLocalDate().plusDays( 1 ) , alarmTime , z );
}
To calculate the elapsed time until the alarm, use the Duration class.
Duration untilAlarm = Duration.between( now , alarm );
You can interrogate the duration for a total number of milliseconds. But know that java.time classes are capable of handling nanoseconds.
long millis = untilAlarm.toMillis();
Updated.
You are using only time without a date with you date object in code (parses only time). If you add there date to you time, your date should be comparable to your System.getCurrentTimeMillis() call. And if you subtracting current millis from date in the past, you will have negative numbers. I prefer this convertion (date2 is after date1):
long diffInMillies = date2.getTime() - date1.getTime();
return TimeUnit.convert(diffInMillies, TimeUnit.MILLISECONDS);
I have some time Strings such as "09:00" and "17:30" and I need to check if the current time is between that range.
I thought I could make this comparison:
SimpleDateFormat format = new SimpleDateFormat("HH:mm");
Date now = new Date();
Date begin;
Date end;
begin = format.parse(begin_string);
end = format.parse(end_string);
if (now.compareTo(begin) > 0 && end.compareTo(now) > 0)
return true;
else
return false;
Turns out that when I parse the strings, the times are parsed correctly, but the date is set to Jan 1st 1970. This way, the code will always return false.
I'd like to know how can I set begin and end to the current date, but with the times from their strings.
You could also just reuse your format object for current time like this way:
SimpleDateFormat format = new SimpleDateFormat("HH:mm");
Date now = new Date();
String time = format.format(now); // format to wall time loosing current date
System.out.println(time);
now = format.parse(time); // reparse wall time
System.out.println(now);
So you transform now to 1970 using implicitly the standard time zone of your system and can then use it for direct comparisons with begin and end.
Date begin = format.parse("09:00");
Date end = format.parse("21:30");
return (begin.before(now) && end.after(now)); // open-bounded interval
Get current time, Calendar.getInstance();
Get another 2 instance of current time, and set time fields based on your input
For example:
Calendar.set(Calendar.HOUR_OF_DAY, 1);
and invoke compare() on the boundry of time
You should really use a Calendar. Then you can individually set the hours and minutes from values parsed from the string. Then get the time in milliseconds and compare those.
Date now = new Date();
Calendar cal = Calendar.getInstance();
cal.setTime(now);
cal.set(Calendar.HOUR_OF_DAY, hours);
cal.set(Calendar.MINUTE, minutes);
long time = cal.getTimeInMillis();
You could also use the wonderful Joda library. In my opinion Joda is a much better way to work with Dates and Times.
The bundled java.util.Date & .Calendar classes are notoriously troublesome. Avoid them. Use either Joda-Time library or the new java.time package found in Java 8 (inspired by Joda-Time, defined by JSR 310).
If you truly do not care about time zone or date, use either the Joda-Time LocalTime class or the java.time LocalTime class.
Caution: Naïve programmers often think they need only local time and can therefore ignore time zones, but then live to regret that position.
Joda-Time
If your times are in proper ISO 8601 format (24-hours, correct number of digits), then you can directly pass the string inputs to the constructor of LocalTime without bothering to parse. That class has a built-in ISO 8601 style parser.
String inputStart = "09:00";
String inputStop = "17:30";
LocalTime start = new LocalTime( inputStart );
LocalTime stop = new LocalTime( inputStop );
LocalTime now = LocalTime.now();
// Comparing using Half-Open logic, where beginning is inclusive and ending is exclusive.
boolean isNowContainedWithinInterval = ( ( now.isEqual( start ) ) || ( now.isAfter( start ) ) ) && ( now.isBefore( stop ) );
Dump to console…
System.out.println( "start: " + start );
System.out.println( "stop: " + stop );
System.out.println( "now: " + now );
System.out.println( "isNowContainedWithinInterval: " + isNowContainedWithinInterval );
When run…
start: 09:00:00.000
stop: 17:30:00.000
now: 12:42:06.567
isNowContainedWithinInterval: true
In the real-world, I would add an assertion test proving the stop time is later than the start time, to validate inputs.
I have a date in Integer format(YYYYMMDD). And a start_time as a String (HH:mm 24 hour system). and a time_duration in hours as a double.
int date = 20140214;
String start_time = "14:30";
double duration = 50.30;
I want to use these 3 values and create 2 Java Date Objects. One is start_date and one is end_date. They should be in the format YYYY-MM-DD HH:mm.
And then after I get 2 data Strings like YYYY-MM-DD HH:mm. how can I obtain those previous variables. date, start_time, duration.
This is my attempt.
public void solve() throws IOException {
int date = 20140214;
String start_time = "14:30";
double duration = 24.50;
String startDate = "";
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm");
startDate = getDate(date) + " " + start_time;
try {
Date start_Date = df.parse(startDate);
Date end_Date = new Date(start_Date.getTime()+(int)(duration*3600*1000));
System.out.println(df.format(start_Date));
System.out.println(df.format(end_Date));
} catch (ParseException ex) {
}
}
public String getDate(int dateInt) {
String date = "";
String dateIntString = String.valueOf(dateInt);
date = date + dateIntString.substring(0, 4) + "-";
date = date + dateIntString.substring(4, 6) + "-";
date = date + dateIntString.substring(6, 8);
return date;
}
Is there any easy way to do it. ? Or some built-in capabilities I can use other than those I have used ?
Strange Data Types For Date-Time
Using:
An int to represent the digits of a calendar date
A string to represent time-of-day digits
A double to represent a duration of fractional hours
…are all unusual approaches. Probably not the wisest choices in handling date-time values.
Avoid java.util.Date/Calendar
Know that the bundled classes java.util.Date and .Calendar are notoriously troublesome and should be avoided. Use either Joda-Time or the new java.time.* package (Tutorial) in Java 8. And get familiar with the handy ISO 8601 standard.
Time Zone
Your question and example ignore the crucial issue of time zone. Handling date-time data without time zone is like handling text files without knowing their character encoding. Not good.
Use proper time zone names to create time zone object. Avoid the non-standard 3-letter codes.
Joda-Time
In Joda-Time, a DateTime object is similar to a java.util.Date object but actually knows its own assigned time zone.
Joda-Time offers three classes for representing spans of time: Period, Duration, and Interval.
The Interval class uses the "Half-Open" approach, where the beginning is inclusive and the ending is exclusive. This approach works well for handling spans of time and comparisons. Look for the handy contains, abuts, overlap, and gap methods.
int dateInput = 20140214;
String start_timeInput = "14:30";
double durationInput = 50.30;
// Clean up these inputs.
String datePortion = Integer.toString( dateInput );
String input = datePortion + " " + start_timeInput;
DateTimeFormatter formatterInput = DateTimeFormat.forPattern( "yyyyMMdd HH:mm");
// Specify the time zone this date-time represents.
DateTimeZone timeZone = DateTimeZone.forID( "Europe/Paris" ); // Or, DateTimeZone.UTC
DateTime dateTime = formatterInput.withZone( timeZone ).parseDateTime( input );
// Convert fractional hours to milliseconds, then milliseconds to a Duration object.
long millis = ( 60L * 60L * (long)(1000L * durationInput) ); // 1 hour = 60 minutes * 60 seconds * 1000 milliseconds.
Duration duration = new Duration( millis );
Interval interval = new Interval( dateTime, duration );
DateTimeFormatter formatterOutput = DateTimeFormat.forStyle( "MM" ).withLocale( Locale.FRANCE );
String description = "De " + formatterOutput.print( interval.getStart() ) + " à " + formatterOutput.print( interval.getEnd() );
Dump to console…
System.out.println( "input: " + input );
System.out.println( "dateTime: " + dateTime );
System.out.println( "duration: " + duration ); // Format: PnYnMnDTnHnMnS (from ISO 8601)
System.out.println( "interval: " + interval ); // Format: <start>/<end> (from ISO 8601)
System.out.println( "description: " + description );
When run…
input: 20140214 14:30
dateTime: 2014-02-14T14:30:00.000+01:00
duration: PT181080S
interval: 2014-02-14T14:30:00.000+01:00/2014-02-16T16:48:00.000+01:00
description: De 14 févr. 2014 14:30:00 à 16 févr. 2014 16:48:00
You have very many representations of date.
When in doubt, I usually head for getting to unix standard time (milliseconds since 1970) as soon as possible.
In this case it would be to convert the Integer date to a String, read out the four first as a year, two digits as month and the last two as day day, and then do the similar thing for the 24h time, and create a java.util.Date from this like so:
SimpleDateFormat dateParser=new SimpleDateFormat("yyyyMMdd HH:mm"); //please double check the syntax for this guy...
String yyyyMmDd = date.toString();
String fullDate = yyyyMmDd + " " + start_time;
java.util.Date startDate = dateParser.parse(fullDate);
long startTimeInMillis = startDate.getTime();
final long MILLISECONDS_PER_HOUR = 1000*60*60;
long durationInMillis = (long)duration*MILLISECONDS_PER_HOUR;
java.util.Date endDate = new java.util.Date(startTimeInMillis + durationInMillis);
Don't miss Joda time or Java 8 new, finally improved date handling named java.time.
you can write like
int date = 20140214;
String s=""+date;
Date date = new SimpleDateFormat("yyyyMMdd").parse(s);
This question already has answers here:
Java 8 Date and Time: parse ISO 8601 string without colon in offset [duplicate]
(4 answers)
Closed 3 years ago.
StrDate = "2011-07-19T18:23:20+0000";
How can I get an epoch time for the above date format in android
also I would like to know how to convert a epoch time to the above date format.
I would appreciate a direct answer with an example.
Example code using Joda-Time 2.3.
Unix time is number of seconds since beginning of 1970 in UTC/GMT.
How can I get an epoch time for the above date format in android
DateTime dateTimeInUtc = new DateTime( "2011-07-19T18:23:20+0000", DateTimeZone.UTC );
long secondsSinceUnixEpoch = ( dateTimeInUtc.getMillis() / 1000 ); // Convert milliseconds to seconds.
…and…
how to convert a epoch time to the above date format.
String dateTimeAsString = new DateTime( secondsSinceUnixEpoch * 1000, DateTimeZone.UTC ).toString();
To dump those values to the console…
System.out.println( "dateTimeInUtc: " + dateTimeInUtc );
System.out.println( "secondsSinceUnixEpoch: " + secondsSinceUnixEpoch );
System.out.println( "dateTimeAsString: " + dateTimeAsString );
Bonus: Adjust to another time zone.
DateTime dateTimeMontréal = dateTimeInUtc.withZone( DateTimeZone.forID( "America/Montreal" ) );
You should use SimpleDateFormat. That class both supports formatting, and parsing.
Sample code:
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ssZZZZ");
Date gmt = formatter.parse("2011-07-19T18:23:20+0000");
long millisecondsSinceEpoch0 = gmt.getTime();
String asString = formatter.format(gmt);
Note that a Date instance in Java, always represent milliseconds since epoch 0, in UTC/GMT, but it is printed in local time when you print it.
To answer your question a bit late but Joda-Time will be able to handle both in a simply and clean way.
Using Joda-Time
1.Epoch time to Date
Where date is your epoch time
DateTime dateTime = new DateTime(date*1000L);
System.out.println("Datetime ..." + dateTime);
Datetime from Epoch ...2014-08-01T13:00:00.000-04:00
2.Date to epoch
DateTime fromDate = new DateTime("2011-07-19T18:23:20+0000");
long epochTime = fromDate.getMillis();
System.out.println("Date is.." + fromDate + " epoch of date " + epochTime);
Date is..2011-07-19T14:23:20.000-04:00 epoch of date 1311099800000
In java, how can I find out if a specific date is within 1 year of today's date.
I have the following but not sure if this is the best approach.
String date = "01/19/2005";
DateFormat df = new SimpleDateFormat("dd/MM/yyyy");
Date lastExamTakenDate = null;
Calendar todaysDateMinus1Year = Calendar.getInstance();
todaysDateMinus1Year.add(Calendar.YEAR, -1);
if (date!=null)
{
try {
lastExamTakenDate = df.parse(date);
if (lastExamTakenDate.before(todaysDateMinus1Year.getTime()))
hasToTakeExam = true;
} catch (ParseException ex) {
//exception
}
}
The java.util.Date & .Calendar classes bundled with Java are notoriously troublesome. Avoid them. Use either Joda-Time or the new java.time package bundled with Java 8 (and inspired by Joda-Time).
Joda-Time
If you are certain you want date only without time or time zone, use the LocalDate class (found in both Joda-Time and java.time).
Note the use of a time zone when asking for the current date. The date varies depending on where you are at on earth at the moment. If you fail to specify a date, the JVM’s default time zone will be used. Generally better to specify.
Here is some example code using Joda-Time 2.3.
String input = "01/19/2005";
DateTimeFormatter formatter = DateTimeFormat.forPattern( "MM/dd/yyyy" );
LocalDate localDate = LocalDate.parse( input, formatter );
DateTimeZone timeZone = DateTimeZone.forID( "Europe/Paris" );
LocalDate now = LocalDate.now( timeZone );
LocalDate yearAgo = now.minusYears( 1 );
boolean withinYearAgo = ( ( localDate.isAfter( yearAgo ) ) & ( localDate.isBefore( now ) ) );
Dump to console…
System.out.println( "input: " + input );
System.out.println( "localDate: " + localDate );
System.out.println( "now: " + now );
System.out.println( "yearAgo: " + yearAgo );
System.out.println( "withinYearAgo: " + withinYearAgo );
When run…
input: 01/19/2005
localDate: 2005-01-19
now: 2014-04-10
yearAgo: 2013-04-10
withinYearAgo: false
You might want to add a test for "or is equal to" depending on your definition of "within last year".
If you call getTime() on a date object it will return a long with milliseconds since epoch (jan 1. 1970). Checking if a date is within the last year is then a simple matter of creating one date object with a date one year ago and doing comparison on the long values (someDate > aYearAgo). Alternatively you can use the after() method on a calendar object. To create a calendar/date object with a value one year ago you can use calObj.add(Calendar.YEAR, -1).
I believe something like this will get you the start of the calendar day so that time of day is not a factor.
GregorianCalendar calToday = new GregorianCalendar();
GregorianCalendar oneYearAgoTodayAtMidnight = new GregorianCalendar(calToday.get(Calendar.YEAR) - 1, calToday.get(Calendar.MONTH), calToday.get(Calendar.DATE));
This approach ignores leap-years (and other calendar-caused oddities), but is very straightforward:
public boolean isWithinAYear(Date inputDate) {
Date d = new Date() // Get "now".
long dLong = d.getTime();
// You could multiply this next line out and use a single constant,
// I didn't do that for clarity (and the compiler will optimize it
// out for us anyhow.)
long oneYearAgo = dLong - (365 * 24 * 60 * 60 * 1000);
return inputDate.getTime() > oneYearAgo;
}
Your solution using GregorianCalendar is technically more correct.
This woks perfectly.
public class X {
public static Date date ;
public static Date date1 ;
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
Calendar cal = Calendar.getInstance();
cal.add(Calendar.YEAR, 0);
boolean time;
date = cal.getTime();
System.out.println(date);
time = withinYear(date);
System.out.println(time);
}
private static boolean result;
public static boolean withinYear(Date inputDate)
{
Calendar todaysDateMinus1Year = Calendar.getInstance();
todaysDateMinus1Year.add(Calendar.YEAR, -1);
date1 = todaysDateMinus1Year.getTime();
if (inputDate.before(date1))
result= true;
return result;
}