Spring Boot JPA TimeZone - spring

I am having some troubles whit an endpoint that returns an object that contains a date (this date comes from a web service response).
So, right now these are the steps
I read the response from the webservice, and i set it on the "TicketAcceso" object.
//example
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
System.out.println("Read from the xml response = "+dateLineXmlResponse);
//OUTPUT = "Read from the xml response = 2019-09-27T01:56:14.467-03:00"
Date expDate = new Date(dateFormat.parse(dateLineXmlResponse).getTime());
ticketAcceso.setFechaVencimiento(expDate);
Save the object (actually from a bigger class, "Session", that contains one "TicketAcceso"), this is working, the date is now saved in mysql.
Then i have a get endpoint that returns a TicketAcceso, the thing is:
. The Date is correct in the database (OK value, without timezone info).
. If i get the date from the object just before returning from the endpoint, the value is ok (it uses the local timezone)
System.out.println("Getting the date from the object before returning =
"+ticketAccesoNuevo.getFechaVencimiento());
//OUTPUT = "Getting the date from the object before returning = Fri Sep 27 01:56:14 ART 2019"
//returns the TicketAcceso
BUT
The endpoint returns the date in UTC timezone
Actual MySQL value =
Endpoint return value =
Is there a way for returning the date in the local TimeZone? I've already added these lines:
spring.datasource.url=jdbc:mysql://${MYSQL_HOST:localhost}:3306/db_example?
useLegacyDatetimeCode=false
spring.jpa.properties.hibernate.jdbc.time_zone=America/Argentina/Buenos_Aires</code>

Related

Elastic search update-by-query how work with date field (parse from string?)

I'm new in elastic and I need work with date in update-by-query script.
I have docs with field expire which is mapped as date.
I try in my script in update-by-query:
SimpleDateFormat expire = new SimpleDateFormat(\"yyyy-MM-dd'T'HH:mm:ss Z\", Locale.getDefault());
long expireTime = expire.parse(ctx._source.expire).getTime();
But there is error: Unparseable date: "2017-07-21T11:19:42+02:00"
Is there a different way, how got date object or UNIX timestamp?
Or is there a way how got mapped formats instead of strings in update-by-query?
Thank you.
There's some documentation on working with dates in scripts. Just do this and it will work:
long expireTime = ZonedDateTime.parse(ctx._source.expire).toInstant().toEpochMilli()

Wrong LocalDate stored with hibernate

I'm trying to store inside the database the date of a restaurant booking but, even though the date I submit is correct, hibernate stores inside the database a date one day before the one I submitted. I don't know why... it's probably a timezone problem but I can't understand why... the date should not be affected by the timezones.
Here is my spring boot properties file:
spring:
thymeleaf:
mode: HTML5
encoding: UTF-8
cache: false
jpa:
database: MYSQL
hibernate:
ddl-auto: update
properties:
hibernate:
locationId:
new_generator_mappings: false
dialect: org.hibernate.dialect.MySQL5InnoDBDialect
jdbc:
time_zone: UTC
datasource:
driver:
class: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/databaseName?useSSL=false&useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
username: username
password: **********
I'm from Italy, so my timezone is this:
GMT/UTC + 1h during Standard Time
GMT/UTC + 2h during Daylight Saving Time
Currently we are UTC + 2h.
The object I'm storing is this one:
#Entity
public class Dinner {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long dinnerId;
private LocalDate date;
...
The controller I'm using to intercept the POST request is this:
#PreAuthorize("hasRole('USER')")
#PostMapping
public String createDinner(#RequestParam(value="dinnerDate") String dinnerDate, Principal principal, Model model){
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
LocalDate date = LocalDate.parse(dinnerDate, formatter);
dinnerService.createDinner(date);
return "redirect:/dinners?dinnerDate=" + dinnerDate;
}
Which calls the service method createDinner that call the Jpa method save to store the object.
I'm using thymeleaf to handle the html templates.
If I submit the date 30/6/2019 inside the database I get 29/6/2019. When I retrieve the Dinner object by date, if I insert 30/6/2019, I get the Dinner with the date 29/6/2019. So it seems that spring handle the date by itself in a weird way... considering some sort of timezone but I don't know how to disable or handle it. Any idea?
You do not need to define a format for the pattern yyyy-MM-dd. LocalDate#parse uses DateTimeFormatter.ISO_LOCAL_DATE by default which means LocalDate.parse("2020-06-29") works without applying a format explicitly.
Since you already know that date-time in your time-zone is different from that in UTC, you should never consider just a date; rather you should consider both date and time e.g. 11:30 PM at UTC on 2020-06-29 will fall on 2020-06-30 in your time-zone. Therefore, the first thing you should do is to change the type of the field as TIMESTAMP in the database.
Once you have changed the type of the field to TIMESTAMP, change the method, createDinner as follows:
LocalDateTime dinnerDateTime = LocalDateTime.of(LocalDate.parse(dinnerDate), LocalTime.of(0, 0, 0, 0));
OffsetDateTime odt = dinnerDateTime.atOffset(ZoneOffset.UTC);
dinnerService.createDinner(odt);
Then inside DinnerService (or DinnerServiceDAO wherever you have written the logic to insert/update record in the database):
pst.setObject(index, odt);
where pst represents the object of PreparedStatement and index represents the index (starting with 1) of this field in your insert/update query.
same problem (and same country! :-) ).
I suspect that if hibernate or jpa are set with timezone UTC, while the machine is set with default timezone == Europe/Rome when a date is persisted, then it will be converted automatically from machine timezone to database timezone, which is not a bad feature if you have all dates stored in UTC format on the DB.
The problem happens when you convert the date before persisting: it gets converted twice. At least, this is my case.
Still looking for the best solution! In case I'll find one, then I'll add it later to the answer.
Assuming your time zone is : Europe/Italy , You have to set up your serverTimezone variable like this :
url: jdbc:mysql://localhost:3306/databaseName?useSSL=false&useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Europe/Italy

How can i change timezone in neo4j?

I want to change default timezone from UTC to another timezone. How it will be possible? I tried
RETURN apoc.date.format(timestamp(),'ms', 'yyyy/MM/dd HH/mm/ss')
but it returns utc time on localhost.
Example answer:
RETURN apoc.date.format(timestamp(),'ms', 'yyyy/MM/dd HH:mm:ss',"Europe/Paris")
Method from the source:
public String format(final
#Name("time") Long time
,#Name(value = "unit", defaultValue = "ms") String unit
,#Name(value = "format",defaultValue = DEFAULT_FORMAT) String format
,#Name(value = "timezone",defaultValue = "") String timezone)
{
return time == null ? null : parse(unit(unit).toMillis(time), format, timezone);
}
The timezone parameter is further passed to Java TimeZone class constructor.
From Java documentation as to what it should contain -
the ID for a TimeZone, either an abbreviation such as "PST", a full
name such as "America/Los_Angeles", or a custom ID such as "GMT-8:00".
Note that the support of abbreviations is for JDK 1.1.x compatibility
only and full names should be used.
The source code of this project -
https://github.com/neo4j-contrib/neo4j-apoc-procedures/blob/3.3/src/main/java/apoc/date/Date.java
For more info, have a look at this article about dates in APOC
http://xclave.azurewebsites.net/2018/02/28/better-know-apoc-apoc-3-date-parse-format/

Web API DateTime not being parsed

I am receiving POST data from a vendor's web service in my web api. One of the values being sent is a data and time - sample: StartTime=2014-10-20+15%3A30%3A54. I understand that %3A is an escape for :, which would have a date in the following format: 2014-10-20+15:30:54.
The problem is that the StartTime value is not being parsed properly by the web api, and all the StartDate properties on my model are being set to 1/1/0001 12:00:00 AM.
Can anyone point me in the right direction here? I can't seem to find any info on what format this date is in to see if there is a way to have the web api framework parse it correctly.
Try this
Request Body:
{"StartTime":"2014-10-20+15:30:54"}
Parse:
CultureInfo provider = CultureInfo.InvariantCulture;
string format = "yyyy-MM-dd+HH:mm:ss";
DateTime dt = DateTime.ParseExact(request.StartTime, format, provider);

How do I extract the created date out of a Mongo ObjectID

I'm using the Mongo shell to query my Mongo db. I want to use the timestamp contained in the ObjectID as part of my query and also as a column to extract into output. I have setup Mongo to create ObjectIDs on its own.
My problem is I can not find out how to work with the ObjectID to extract its timestamp.
Here are the queries I am trying to get working. The 'createdDate' field is a placeholder; not sure what the correct field is:
//Find everything created since 1/1/2011
db.myCollection.find({date: {$gt: new Date(2011,1,1)}});
//Find everything and return their createdDates
db.myCollection.find({},{createdDate:1});
getTimestamp()
The function you need is this one, it's included for you already in the shell:
ObjectId.prototype.getTimestamp = function() {
return new Date(parseInt(this.toString().slice(0,8), 16)*1000);
}
References
Check out this section from the docs:
Extract insertion times from _id rather than having a separate timestamp field
This unit test also demostrates the same:
mongo / jstests / objid6.js
Example using the Mongo shell:
> db.col.insert( { name: "Foo" } );
> var doc = db.col.findOne( { name: "Foo" } );
> var timestamp = doc._id.getTimestamp();
> print(timestamp);
Wed Sep 07 2011 18:37:37 GMT+1000 (AUS Eastern Standard Time)
> printjson(timestamp);
ISODate("2011-09-07T08:37:37Z")
This question is helpful to understand of how to use the _id's embedded timestamp in query situations (refers to the Mongo Extended JSON documentation). This is how it's done:
col.find({...,
'_id' : {'$lt' : {'$oid' : '50314b8e9bcf000000000000'}}
})
finds documents created earlier than the one that's given by oid. Used together with natural sorting and limiting you can utilize BSON _ids to create Twitter-like API queries (give me the last OID you have and I'll provide twenty more)
In python you can do this:
>>> from bson.objectid import ObjectId
>>> gen_time = datetime.datetime(2010, 1, 1)
>>> dummy_id = ObjectId.from_datetime(gen_time)
>>> result = collection.find({"_id": {"$lt": dummy_id}})
I think, ObjectId.from_datetime() - its a useful method of standard bson lib
Maybe other language bindings have alternative builtin function.
Source: http://api.mongodb.org/python/current/api/bson/objectid.html
To use the timestamp contained in the ObjectId and return documents created after a certain date, you can use $where with a function.
e.g.
db.yourcollection.find( {
$where: function() {
return this._id.getTimestamp() > new Date("2020-10-01")
}
});
The function needs to return a truthy value for that document to be included in the results. Reference: $where
Mongo date objects can seem a bit peculiar though. See the mongo Date() documentation for constructor details.
excerpt:
You can specify a particular date by passing an ISO-8601 date string with a year within the inclusive range 0 through 9999 to the new Date() constructor or the ISODate() function. These functions accept the following formats:
new Date("<YYYY-mm-dd>") returns the ISODate with the specified date.
new Date("<YYYY-mm-ddTHH:MM:ss>") specifies the datetime in the client’s local timezone and returns the ISODate with the specified datetime in UTC.
new Date("<YYYY-mm-ddTHH:MM:ssZ>") specifies the datetime in UTC and returns the ISODate with the specified datetime in UTC.
new Date(<integer>) specifies the datetime as milliseconds since the Unix epoch (Jan 1, 1970), and returns the resulting ISODate instance.

Resources