DynamoDB table scan based on dates - Java - java

I've got a requirement, in my application, whereby I need to check a DynamoDB table for updates at regular intervals. Precisely, The field I need to check is not the hash key, and therefore I cannot query -- I need to scan.
The scan filter I am trying to build needs to check a field containing a date (coded as a String in the table), and the logic I am using is the one of asking all records created or updated in the last hour. The snippet I am using is below:
Condition scanFilterCondition = new Condition()
.withComparisonOperator(ComparisonOperator.BETWEEN.toString())
.withAttributeValueList(new AttributeValue().withS(new Date(currentTime-3600000).toString()),
new AttributeValue().withS(new Date(currentTime).toString()));
It seems to be correct, however it seems to always return an empty set so it is ovviously not correct.
I've been googling around to understand why this is not correct, however I haven't found anything around scanning/querying DyanmoDB on dates.
Any ideas on the fault?

Is the string written in the table as an EPOCH timestamp (e.g. 1382199953)? with or without milliseconds?
The default toString() returns a locale-based human-readable string (e.g. dow mon dd hh:mm:ss zzz yyyy).
If that's not the case, please comment with a sample data from the field in question.
Edit to support ISODateTime format using Joda:
DateTimeFormatter dateFormatter = ISODateTimeFormat.dateTime().withZoneUTC();
String isoDate = dateFormatter.print(currentTime);

Related

Problem showing correct HBase date type in Apache Phoenix

I got problem while reading date format data which created through hbase api (using 'put' command) from apache phoenix.
This is the date format what i expected :
Date : 2018-12-17T21:21:45+07:00 into
'yyyy-MM-dd' => '2018-12-17'
The table is created from phoenix client using below DDL :
CREATE TABLE "TEST"
(
ID VARCHAR,
"col1".TRX_DATES UNSIGNED_DATE
CONSTRAINT PKD PRIMARY KEY (ID)
)
But, when i'm trying to query the data, it shows incorrect date format :
292269006-11-18
I've tried some research and experiment using various data type to insert date to hbase, include using long value (milliseconds) of the date. But still, it cannot show the correct date value in phoenix ('yyyy-MM-dd')
Any suggestions for this case?
Maybe this should have been a comment because I cannot explain all the details of what has gone wrong nor how you can fix it. But I can see that your problem comes from an inversion of the sign bit of the milliseconds since the epoch. I tried this:
long milli = OffsetDateTime.parse("2018-12-17T21:21:45+07:00").toInstant().toEpochMilli();
milli += Long.MIN_VALUE; // Flip the sign bit
Date wrongDateAsOldfashiondDate = new Date(milli);
System.out.println(wrongDateAsOldfashiondDate);
System.out.println(new SimpleDateFormat("yyyy-MM-dd").format(wrongDateAsOldfashiondDate));
The output on my computer (in Europe/Copenhagen time zone) was:
Fri Nov 18 08:08:49 CET 292269006
292269006-11-18
Normally one shouldn’t use the old and poorly designed Date class, but this was the way I could get exactly the same result as yours. The difference from the modern date and time API is that Date uses the Julian calendar, so apparently this was also used by the software giving your unexpected result (probably the Date class was involved there too).

Java, date from string without pattern

I need to get a Date instance from input file. I don't know the date format, but I want to get it from user profile settings.
Te following code does not working:
DateFormat form = DateFormat.getDa​teInstance(DateF​ormat.SHORT, Locale.getDefaul​t());
try {
Date t = form.parse("6/6/2015");
}
unparseable date error
I want to know if there is any way to get date from string without knowing the date string pattern.
I need this date to create MySQL query. Maybe there is another way to build this query without parsing date? I am using Entity Beans.
No. Consider the date "1/2/2015": is that February 1st or January 2nd. Depends on your locale.
Instead, you should be more specific: rather than getting a date formatter for your locale, use SimpleDateFormat with an explicit pattern.
I want to know if there is any way to get data from string without knowing the data string pattern.
Without any more information, this is very error prone. For example, consider "7/6/2015" - does that mean June 7th, or July 6th?
If you know the user's locale, you can do a lot better - for example, you could obtain DateFormat instances for long, medium, short and full date patterns for that locale, and try them one at a time. Bear in mind, however, that depending on where this code is executing, the default locale (as you're using at the moment) may not be the user's locale. You mention the user profile settings - hopefully that already contains a locale.
One alternative is to ask the user to tell you what the format is - maybe provide lots of different examples, and let them pick the one that matches.
Finally, if the file has lots of dates in and you're confident they'll all be in the same format, you could try to parse all of them in each of several different formats - that's likely to reduce the chances of error, as "7/6/2015" becomes unambigious if you've also seen "13/1/2015" for example.

Hibernate stores Calendar as int when using SQLite

I am using Hibernate 4.3.8 along with a SQLite database (sqlite-jdbc-3.8.7.jar). Some of the mapped objects contain Calendar-attributes, e.g. startDate and endDate. After Hibernate got problems with reading dates in the format yyyy-MM-dd (e.g. 2015-01-01), I added the following line to hibernate.cfg.xml:
<property name="connection.date_string_format">yyyy-MM-dd</property>
Reading from the database works now, but when I save an object, Hibernate should save the date in the correct format but saves the time in milliseconds since 1970. After that, reading from the database again results in an error, since the columns now have values like 1427410800105, which are of course not the right format. Btw., I'm using the SQLiteDialect from here, there should be nothing wrong with that.
Are there maybe some annotations that can help me?
Personally, I only want to change some things in the configuration or in the dialect, I don't want to go through all my objects and do changes there. And of course I don't want to change the type Calendar to Date, because this would mean too much changes to the code.
UPDATE: Using #Temporal(value = TemporalType.DATE) does not work. The column entries stay the same.
UPDATE2: The same goes for #Column(columnDefinition = "calendar")
After some research I found the CalendarDateType. As I see it, Hibernate stores the Calendar attributes as timestamp by default. MySQL seems to convert this to a DATE or a DATETIME, but as SQLite has no such type, all date values are stored as TEXT. Saving a Calendar as timestamp results in these ugly numbers. To change the way Hibernate handles Calendar, just add the #Type-annotation:
#Type(type = "org.hibernate.type.CalendarDateType")
Calendar someAttribute;
If the Calendar should be saved in another format, you can define your own implementation of UserType like in this question: Hibernate - Mapping java.util.Calendar to MySQL BIGINT
UPDATE:
I tried to use the CalendarDateType from Hibernate, but for some reason, it didn't work. A quick look at the source code also shows that Hibernate uses another date format (dd MMMM yyyy), so it could make things problematic. To handle this I wrote my own implementation of UserType as described in the link above.

What is the efficient way to store date in mongodb.?

I have a JSON file which has 40k documents, each document contains a date field. I need to query within Java with dates to retrieve data, so I stored the date in numberLong format.
Date dt = new Date();
SimpleDateFormat format = new SimpleDateFormat("MM/dd/yyyy");
dt = format.parse(nextLine[j]);
document.put(ColumnNameAsKey[j], dt.getTime());
where the above code is done in for loop in an API to store data to mongo.
But after entering all those data, and then when I queried numberlong changes automatically for the same date, so that I am unable to retrieve all data for the required date. My query to retrieve is
querygraph.put("Complaint Date (MM/DD/YYYY)", new
BasicDBObject("$gte",startdate.getTime()).append("$lte",EndDate.getTime()));
for eg : if the date 08/01/2012 contains large number of document, the correct numberlong for the date 08/01/2012 is replaced in the date field in mongo. this will continue, but aftr some number of documents, the numberlong keep on changing.. ie if NumberLong is 134353300000 for the date 08/01/2012, then after 6 or more document the numberlong will be different from the former one.. causing unable to retrieve exact data for the date 08/01/2012..
What makes the difference here?
I think see your problem, because you store the millisecond precision of time you are actually getting problems with the long ints representing parts of a day making it impossible to query past, say, midnight.
This is because MongoDB querying does not take this sort of contextual querying into account.
First off a hint, don't store as number longs, store as the $date BSON type using only the lines:
Date dt = new Date();
SimpleDateFormat format = new SimpleDateFormat("MM/dd/yyyy");
You will get more functionality from using the specified BSON date type and the querying ability is the same across the board.
You have the right idea about querying your records:
querygraph.put("Complaint Date (MM/DD/YYYY)", new
BasicDBObject("$gte",startdate.getTime()).append("$lte",EndDate.getTime()));
But I got a feeling you are doing something wrong. When you create the start date and the end date you are actually looking for the 00:00:00 time of the start date and the 23:59:59 time of the end date. This is due to your getTime() function, UNIX timestamp does not return partial times as such it will just return the default which is effectively now().
One way around that could make your life easier is to standardise times on this field so that you specify a time of 00:00:00 for all dates allowing you pick out ranges correctly.

Java date - 12am is stored as 24?

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.

Categories

Resources