How to compare Google Appengine DateTime against a Date object in Java? - java

I am new to Google Appengine. In my application, the datastore entities store a java.util.Date object. I want to query the datastore to return all the entities before a particular time. My code for this is :
Date date = new Date();
Query<Event> query = ofy().load().type(Event.class).order("date");
query = query.filter("date <", date);
which upon execution, gives the error : Invalid date/time format: Sat Apr 04 00:40:22 IST 2015
If this format is invalid, which format do I need to use to query?

Here is a simple code
import java.util.Date;
import com.googlecode.objectify.annotation.Entity;
import com.googlecode.objectify.annotation.Id;
import com.googlecode.objectify.annotation.Index;
#Entity
public class EntityDate {
public EntityDate() {
// Objectify needed
}
#Id
private Long id;
#Index
public Date date;
}
and here the code which makes the query
Date date = new Date();
Objectify ofy = ObjectifyService.ofy();
ObjectifyService.register(EntityDate.class);
EntityDate entityDate = new EntityDate();
entityDate.date = date;
ofy.save().entities(entityDate);
Query<EntityDate> ofyQuery = ofy.load().type(EntityDate.class).order("date");
ofyQuery = ofyQuery.filter("date <", date);
List<EntityDate> list = ofyQuery.list();
Logger.getLogger("EntityDate").info(list.toString());
The entities are correctly saved
and the query provides the 4 results
[EntityDate#6780874d, EntityDate#27330551, EntityDate#6a21cf2, EntityDate#7d1a5744]
The default toString() of the class is a bit ugly, but it makes the point about the query correctly executed.
Can you provide the source of your Event class and the continuation of your code which execute the query?

Related

How to add a Timestamp in Firestore with Android?

I am trying to add a timestamp field in an Android client with Firebase Firestore.
According to the documentation:
Annotation used to mark a Date field to be populated with a server
timestamp. If a POJO being written contains null for a
#ServerTimestamp-annotated field, it will be replaced with a
server-generated timestamp.
But when I try it:
#ServerTimestamp
Date serverTime = null; // I tried both java.util.Date and java.sql.Date
//...
Map<String, Object> msg = new HashMap<>();
// ... more data
msg.put("timestamp", serverTime);
On the Cloud Firestore database this field is always null.
That is not the correct way of how to add the time and date to a Cloud Firestore database. The best practice is to have a model class in which you can add a date field of type Date together with an annotation. This is how your model class should look like:
import java.util.Date;
public class YourModelClass {
#ServerTimestamp
private Date date;
YourModelClass() {}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
}
When you create on object of YourModelClass class, there is no need to set the date. Firebase servers will read your date field, as it is a ServerTimestamp (see the annotation), and it will populate that field with the server timestamp accordingly.
Another approach would be to use FieldValue.serverTimestamp() method like this:
Map<String, Object> map = new HashMap<>();
map.put("date", FieldValue.serverTimestamp());
docRef.update(map).addOnCompleteListener(new OnCompleteListener<Void>() {/* ... */}
use FieldValue.serverTimestamp() get server timestamp
Map<String, Object> msg = new HashMap<>();
msg.put("timestamp", FieldValue.serverTimestamp());
I have similar problem, and I found this at my catlog and solved my problem
firebaseFirestore = FirebaseFirestore.getInstance();
FirebaseFirestoreSettings settings = new FirebaseFirestoreSettings.Builder()
.setTimestampsInSnapshotsEnabled(true)
.build();
firebaseFirestore.setFirestoreSettings(settings);
I had a similar problem,
I was getting the exception ...has type java.sql.Timestamp, got java.util.Date ..., so I just replace the type from Timestamp to Date ( from java.util.Date) and worked fine.

Spring hibernate unwanted timezone adjustment

I have a simple service that takes a date in as a String (amongst other fields) and saves it to a mySql database. I am using Spring Boot with Hibernate.
If I post JSON with {"expenseDate":"04/02/2017"} the date that is being captured after the jackson mapping is "2017-04-01 19:00:00".
Incidentally, if I look at the row in the database, the date is "2017-04-02" just as I would expect. When I query the service, the date that comes back in the json is correct, but when I dump out the rows from the database, they all return the correct day minus six hours.
I live in the central time zone, so my guess is that the date in the database is UTC and Spring is taking six hours off for being in central time.
Controller:
#PostMapping("/expenses")
public ResponseEntity<Expense> submitExpense(#RequestBody Expense expense) throws BadHttpRequest {
expenseService.saveExpense(expense);
return new ResponseEntity<>(expense, HttpStatus.CREATED);
}
Entity:
#Entity
public class Expense {
#Id
#GeneratedValue
Integer id;
Double cost;
String location;
String expenseType;
String description;
#JsonFormat(pattern = "MM/dd/yyyy")
Date expenseDate;
I tried #JsonFormat(pattern = "MM/dd/yyyy", timezone = "UTC") on the date field but it changed nothing.
I also tried constructing the date from the view using the date parts and passing it as a long down to the service, but the result is the same. clearly I'm missing something excruciatingly vital and, likely, simple.
any thoughts?
You should set the "timezone" to whatever timezone you expect the incoming date to be in.
public class Data {
#JsonFormat(pattern = "MM/dd/yyyy", timezone="GMT-04:00")
Date date;
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
}
public class Main {
public static void main(String[] args) throws JsonParseException, JsonMappingException, IOException {
ObjectMapper mapper = new ObjectMapper();
Data data = mapper.readValue("{\"date\" : \"04/02/2017\"}", Data.class);
System.out.println(data.date);
}
}
Output
Sun Apr 02 00:00:00 EDT 2017
// I am located in EDT
If I assume the incoming date is in UTC
#JsonFormat(pattern = "MM/dd/yyyy", timezone="UTC")
Date date;
Output
Sat Apr 01 20:00:00 EDT 2017
By default it appears to be considering the date as UTC. In your case if you are in CST you should consider setting Central Time timezone (I believe US/Central).
Note
If your date inputs can come from clients in different timezones that will be another discussion. You will most likely have to define a contract that client enters a date in a particular timezone OR explicitly specify a timezone as additional input OR have your client side (if one exists) do a conversion to a specific timezone that your server-side expects.
There is a database connection url parameter called serverTimezone you may need put.

java.lang.ClassCastException: java.util.Date cannot be cast to java.lang.String when using Univocity

I am trying to read a java.sql.Date field and parse it to a java bean using Univocity with the following code:
public class Example {
public static void main(final String[] args) throws FileNotFoundException {
final BeanListProcessor<Person> rowProcessor = new BeanListProcessor<Person>(Person.class);
final CsvParserSettings parserSettings = new CsvParserSettings();
parserSettings.setProcessor(rowProcessor);
parserSettings.setHeaderExtractionEnabled(false);
parserSettings.getFormat().setDelimiter('|');
final String line = "0|John|12-04-1986";
final CsvParser parser = new CsvParser(parserSettings);
parser.parseLine(line);
final List<Person> beans = rowProcessor.getBeans();
for (final Person person : beans) {
// Expected print: Birthday: 12-04-1986
System.out.println("Birthday: " + person.getBirthDate());
}
}
}
but I am getting the following exception Caused by: java.lang.ClassCastException: java.util.Date cannot be cast to java.lang.String with additional information of com.univocity.parsers.common.DataProcessingException: Error converting value 'Sat Apr 12 00:00:00 CEST 1986' using conversion com.univocity.parsers.conversions.TrimConversion when parsing the line with parser.parseLine(line);
I am trying to represent the Date to how it is in the line e.g. "12-04-1986" and I tried providing the conversion "dd-MM-yyyy", unfortunately to no avail.
What am I missing in my code to get the expected syso of "Birthday: 12-04-1986" ?
EDIT: using java.util.Date
The person class:
// using the correct Date object!
import java.util.Date;
import com.univocity.parsers.annotations.Format;
import com.univocity.parsers.annotations.Parsed;
public class Person {
#Parsed(index=0)
private Integer id;
#Parsed(index=1)
private String name;
#Parsed(index=2)
#Format(formats = "dd-MM-yyyy")
private Date birthDate;
//getters and setters ommited
}
When changing the Date object to a java.util.Date and applying the correct date format on the java.util.Date object the print is correctly displaying the expected result.
The first issue is the conversion sequence you defined:
Conversions.toDate("dd-MM-yyyy"), Conversions.trim()
This generates a Date object, and then applies a String.trim() operation on top of a date instead of a String, which causes the error you just got.
If you change the order this should work:
Conversions.trim(), Conversions.toDate("dd-MM-yyyy")
However, your Person class must have its birthDate field annotated with #Parsed otherwise you'll get a null.
It should be easier to just add the #Format annotation on your birthDate field instead of applying that sequence of conversions. You can just declare your class like this:
public class Person{
#Parsed
String id;
#Parsed
String name;
#Parsed
#Format(formats = "dd-MM-yyyy") //notice that multiple formats are supported
Date birthDate;
}
Finally, notice that the parser trims values by default so you don't need to use the trim conversion or the #Trim annotation unless you disable trimming in the settings.
Hope this helps.

Using joda DateTime Range Key with AWS DynamoDB Object Persistence model

I've got a dynamodb table with a timestamp ("creationDate") as a range. The model is using a joda DateTime to make it easy to use (compatibility with the rest of the code). To be able to make between queries on this range, I used a numeric type for the attribute in the table, and planned to store it as a java timestamp (milliseconds since epoch). Then, I added a marshaller to convert a joda DateTime to a String representing a long and vice-versa.
The table structure (creation):
void CreateTable()
{
CreateTableRequest createTableRequest = new CreateTableRequest().withTableName(LinkManager.TABLE_NAME);
ProvisionedThroughput pt = new ProvisionedThroughput()
.withReadCapacityUnits(LinkManager.READ_CAPACITY_UNITS)
.withWriteCapacityUnits(LinkManager.WRITE_CAPACITY_UNITS);
createTableRequest.setProvisionedThroughput(pt);
ArrayList<AttributeDefinition> ad = new ArrayList<AttributeDefinition>();
ad.add(new AttributeDefinition().withAttributeName("creationDate").withAttributeType(ScalarAttributeType.N));
ad.add(new AttributeDefinition().withAttributeName("contentHash").withAttributeType(ScalarAttributeType.S));
createTableRequest.setAttributeDefinitions(ad);
ArrayList<KeySchemaElement> ks = new ArrayList<KeySchemaElement>();
ks.add(new KeySchemaElement().withAttributeName("contentHash").withKeyType(KeyType.HASH));
ks.add(new KeySchemaElement().withAttributeName("creationDate").withKeyType(KeyType.RANGE));
createTableRequest.setKeySchema(ks);
this.kernel.DDB.createTable(createTableRequest);
}
The model:
#DynamoDBTable(tableName="Link")
public class Link {
private String ContentHash;
private DateTime CreationDate;
#DynamoDBHashKey(attributeName = "contentHash")
public String getContentHash() {
return ContentHash;
}
public void setContentHash(String contentHash) {
ContentHash = contentHash;
}
#DynamoDBRangeKey(attributeName = "creationDate")
#DynamoDBMarshalling(marshallerClass = DateTimeMarshaller.class)
public DateTime getCreationDate() {
return CreationDate;
}
public void setCreationDate(DateTime creationDate) {
CreationDate = creationDate;
}
}
The marshaller:
public class DateTimeMarshaller extends JsonMarshaller<DateTime>
{
public String marshall(DateTime dt)
{
return String.valueOf(dt.getMillis());
}
public DateTime unmarshall(String dt)
{
long ldt = Long.parseLong(dt);
return new DateTime(ldt);
}
}
I get the following error:
Exception in thread "main" com.amazonaws.AmazonServiceException: Type of specified attribute inconsistent with type in table (Service: AmazonDynamoDBv2; Status Code: 400; Error Code: ValidationException; Request ID: 8aabb703-cb44-4e93-ab47-c527a5aa7d52)
I guess this is because the marshaller returns a String, and dynamoDB wants a numeric type, as the attribute type is N. I don't know what people do in this case, I searched for a solution but couldn't find it. I only tested this on a local dynamodb instance, which I don't think makes any difference (this is a validation check failing, there's no request even made).
The obvious workaround is to use long type for the dates in the model and add special getters and setters to work with DateTime. Still, is there a cleaner way ? I am sure I'm not the only one using DatTime range in a model.
What I would do is re-create the table with the Range key as String itself.
Even if it's going to be populated with long numbers, making it type: S will ensure compatibility with the Marshaller

JPA java.util.Date issue

I have date field in the database where the value is "27-AUG-10 15:30:00". I am using JPA to retrieve and set into a model object. In the model object the date is one day extra "2010-08-28 04:00:00.0". When retrieved the date should be 27 Aug 2010, but it is coming 28 Aug 2010 Can you please suggest me why it is retrieving one extra day.
import java.util.Date;
import javax.persistence.Column;
public class Model
{
#Column(name = "BEGIN_DATE")
private Date startDate;
public Date getStartDate() {
return startDate;
}
public void setStartDate(Date startDate) {
this.startDate = startDate;
}
}
The database will by default store the timezone you are in. However in retriving the date out it won't add back the timezone you are in. That date is being displayed as GMT. Look at using JodaTime for a better Date library.
I'll give you an example. You need the JodaTime library and the JadiraTypes library to persist JodaTime dates with Hibernate.
http://mvnrepository.com/artifact/joda-time/joda-time/2.3
http://mvnrepository.com/artifact/org.jadira.usertype/usertype.jodatime/2.0.1
Your code will look something like this:
#Type(type="org.jadira.usertype.dateandtime.joda.PersistentLocalDateTime")
private LocalDateTime date;
This will persist your dates to Hibernate for you.
I'm 90% sure that JodaTime supports adding back the timezone for you. If you are really worried, store them as Timestamps in your database.
Try changing to JodaTime as above and let me know if you have any issues.
I think You should use InitBinder whenever you play with dates between view and controller.
Just put following in your controller
#InitBinder
public void initBinder(WebDataBinder webDataBinder) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
dateFormat.setLenient(false);
webDataBinder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
}

Categories