I am facing issue to display UTC date time in UI.
DB type: postgresql
DB column type: timestamp with time zone
DB column Value: 2021-11-02 22:16:16.108341-04
after read value from DB: 2021-11-02T22:16:16.108341-04:00
UI data: 2021-11-02T22:16:16.108341-04:00
Entity:
private OffsetDateTime createdOn;
from UI we are not able to parse UTC datetime value and display in UI. anyone able to hep me to fix date issue?
By using atZoneSameInstant you could achieve what you are after, if I understood you correctly:
OffsetDateTime time = OffsetDateTime.parse("2021-11-02T22:16:16.108341-04:00");
ZonedDateTime timeInUTC = time.atZoneSameInstant(ZoneId.of("UTC"));
System.out.println(timeInUTC); ///2021-11-03T02:16:16.108341Z[UTC]
atZoneSameInstant
public ZonedDateTime atZoneSameInstant(ZoneId zone)
Combines this date-time with a time-zone to create a ZonedDateTime ensuring that the result has the same instant.
This returns a ZonedDateTime formed from this date-time and the specified time-zone. This conversion will ignore the visible local date-time and use the underlying instant instead. This avoids any problems with local time-line gaps or overlaps. The result might have different values for fields such as hour, minute an even day.
To attempt to retain the values of the fields, use atZoneSimilarLocal(ZoneId). To use the offset as the zone ID, use toZonedDateTime().
Parameters:
zone - the time-zone to use, not null
Returns:
the zoned date-time formed from this date-time, not null
== Edited ==
If you wanted your database to Store the Information in (Your ZONE), but in the UI (UTC), then you need a custom method.
#Entity
public class YourEntity{
private OffsetDateTime createdOn;
public ZonedDateTime getTimeInUTC{
return //convert createdOn;
}
However, why not just save the trouble and configure hibernate to store in UTC directly, if you are worried about "cost" due to conversions?:
How to store date/time and timestamps in UTC time zone with JPA and Hibernate
Related
The SpringBoot Query returns null while using TIMESTAMPTZ as the Datatype, but the Query works for other Datatypes like TIMESTAMP etc. My Date formats are like, "2022-07-24 10:11:29.452+00".
The DB screenshot is added below.
Also the date type is defined as follows
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "datem")
private Date datem;
The API calls the below code
Date start = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").parse("2022-07-24 10:11:29.452+00");
Date end = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").parse("2022-07-24 10:11:49.452+00");
List<MqttMessageParsed> sensor_data = messageParsedRepository.findByCreatedAtBetween(start, end);
The Query function is as follows
#Query("SELECT t FROM MqttMessageParsed t WHERE t.datem BETWEEN :startDate AND :endDate") List<MqttMessageParsed> findByCreatedAtBetween(#Param("startDate")Date start, #Param("endDate")Date end);
The API shoud return the data between the above start and end dates, but it is returning null now. Am i missing something?
Thanks
Avoid legacy classes
You are using terrible date-time classes that were years ago supplanted by the modern java.time classes. Avoid Date, SimpleDateFormat, and Timestamp.
java.time
For a column of a type akin to the SQL standard type TIMESTAMP WITH TIME ZONE, use the class OffsetDateTime in JDBC 4.2 and later.
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;
Writing:
myPreparedStatement.setObject( … , odt);
Hibernate was years ago updated to support java.time. Ditto for Jakarta Persistence, formerly Java Persistence API (JPA).
ISO 8601
I suggest you educate the publisher of your inputs about the value of strict compliance with the ISO 8601 standard for date-time formats.
Replace SPACE in the middle with a T.
Use full offset with both hours and minutes, separated by a COLON character.
So this:
"2022-07-24 10:11:29.452+00"
… should be:
"2022-07-24T10:11:29.452+00:00"
… or alternatively use a Z as the suffix to indicate an offset of zero:
"2022-07-24T10:11:29.452Z"
If you cannot effect that change, then define a custom formatting pattern to parse that non-standard format. Use DateTimeFormatter class, as has been covered many times already on Stack Overflow.
By the way, know that the other data type, TIMESTAMP WITHOUT TIME ZONE cannot be used to record a moment, a specific point on the timeline. This type stores only a date and a time-of-day without the context of a time zone or offset-from-UTC. So, for example, given the date of last January 23rd at 12:00, we cannot know if that meant noon in Tokyo Japan, noon in Toulouse France, or noon in Toledo Ohio US — three different moments several hours apart.
If you need to track when something happened, always use TIMESTAMP WITH TIME ZONE. In the case of Postgres, any time zone or offset info supplied with an input is used to adjust to UTC (an offset of zero) and then discarded. The moment is always stored in UTC, in Postgres for this type. If you care about the original time zone, store that in a second column.
I have an app that creates some entities (it doesn't really matter for this question), but the entities could be created in different timezones, so I have to store UTC offset in my createdAt and updatedAt columns. For some reasons, I'm not able to save generated date correctly, please refer to the code snippet below, to get more details:
Here is what I'm doing:
const { user } = userInfoWebAPICallResult as WebAPICallResult
const now = moment(moment.now())
.tz(user.tz!)
.toDate();
const entity = await Entity.create({
...someData,
createdAt: now
updatedAt: now,
});
I'm getting tz value externally, it's a string which looks like "America/Los_Angeles". If I convert now to string (by calling .format() method) and log the received value I will see something like this "2020-01-03T16:32:53-08:00". As you can see the date has offset value, this is the correct date, but during inspecting the Database I see "2020-01-04 00:32:53.013 00", this string doesn't have offset value anymore and it looks like the resulting date was computed automatically.
I will need to implement the filtration by createdAt date, people from different timezone will use this filtering mechanism. I planned to expose two parameters date and utcOffset via API, which would allow me to return correct entries depending on the user time zone.
What I'm missing?
The moment when the entity was created / updated should probably be stored in UTC; it is a timestamp that identifies an exact point in time when the event happened.
I would suggest dealing with time zones on the output part: convert a UTC timestamp to a display that takes the user's time zone into account.
If you need to know what time of day it was for the user who created or updated the entity, I would store that user's time zone in a separate column, using standard time zone identifiers (like "America/New_York" rather than "EDT" or "EST").
In a scala program, I receive from client side a specific date for instance:
2013-10-20T23:59:59.999Z
and I really want to keep this date when saving into DB and not convert to local, so this line:
debug("--sql timestamp: " + new Timestamp(reading.timestamp.getMillis()))
is printing out: 2013-10-21 02:59:59.999(I am in Romania).
Is there any way I can ignore timezone?
This is Timestamp.toString() behavior. java.sql.Timestamp extends java.util.Date and in its toString() method it uses, in particular, super.getHours(), which, according to javadoc, returns hours interpreted in local timezone - exactly as you observe.
However, internally Timestamp still holds correct timestamp value. There may be problems with storing it to the database, though. See this answer.
2013-10-20T23:59:59.999Z and 2013-10-21 02:59:59.999 are actually the same time: 2013-10-20T23:59:59.999Z is in the UTC time zone (Z), whereas the second one is relative, and expressed as your local time zone (UTC+3 then in Romania).
In PostgreSQL, you should store your timestamps as TIMESTAMP WITH TIME ZONE (TIMESTAMPTZ) in your database to handle this. You'll always be able to print it out later in the time zone you choose then (e.g. UTC). (You might be interested in this recent question to understand why the storage type matters.)
If you want to print out the timestamp in the UTC/Z time zone again, new DateTime(millis, DateTimeZone.UTC) should help (with Joda Time).
I'm having a problem reading dates from a database using JPA. I'm using EclipseLink and PostgreSQL
I've populated my database from a CSV file, witch had dates as strings (in this format: 6/30/2009-23:59:56). I used the following snipet to convert it to a Date object:
public static Date parseDate(String s){
DateFormat formatter = new SimpleDateFormat("d/M/yyyy-k:m:s");
try {
return new Date( ((java.util.Date)formatter.parse(s)).getTime() );
} catch (ParseException ex) {
Logger.getLogger(Type.class.getName()).log(Level.SEVERE, null, ex);
return null;
}
}
The date is correctly converted and stored in the database as expected. Here is how i map the Date object to the database:
#Column(name="data_ts", nullable=false)
#Temporal(TemporalType.TIMESTAMP)
private Date dataTs;
The problem seems to happen when i try to read the Date from the database to use it in a chart(Highcharts). The record with that same timestamp above get read as:
Mon Jun 06 23:59:56 BRT 2011 and it's timestamp as 1307415596000
Note that it is in Brazilian Time(+3h), so the timestamp (that is calculated from GMT) is 3 hours shifted. Once ploted, the timestamp turns to point to 07/06/2011 02:59:56
Here's an example:
List<TimedataEnt> timeData = currentWellsite.getTimeData();
String debug = timeData.get(timeData.size()-1).getDataTs().toString() + ">>>" + timeData.get(timeData.size()-1).getDataTs().getTime();
where currentWellsite is and JPA Entity, and getDataTs() returns a java.util.Date object.
The string turns out to be "Tue Jun 30 23:59:56 BRT 2009>>>1246417196000"
How do I tell JPA not to convert the timestamp read from the database?
As said, Date and Timestamps have no timezone consideration. It seems that the issue is caused because Java considers that the time it reads from the database is the current default timezone.
So, if the database contais 2011-04-04 14:00:00 and my current timezone is +3, assigning that to java Date will generate 2011-04-04 14:00:00 BRT time(+3), with a timestamp shifted 3 hours (since timestamps are caclulated from UTC).
Solved the issue by getting an calculated timestamp:
long ts = myDate().getTime() + TimeZone.getDefault().getRawOffset();
It's important to say that getRawOffset() does not take Daylight Saving periods in consideration. For that, use getOffset()
Your date is 6/30/2009-23:59:56. I read that as 30 june 2009, 23:59:56. So the format to parse it should be M/d/yyyy-HH:mm:ss or M/d/yyyy-kk:mm:ss (depending on if your hours go from 1 to 24 or from 0 to 23). But definitely not d/M/yyyy-k:m:s: the month comes before the day.
Also, a Timestamp doesn't have any time zone. It's a universal instant in time. It's only when you display its value that the timezone is important, because then you have to choose which time zone to use to display the time. Use a DateFormat with the appropriate timezone set to display your timestamp.
Your issue seems to be that you are storing your Timestamp (which does not have a timezone) into a java.util.Date (which has a timezone offset).
If you want control over how the timezone is set, then store your Timestamp as a java.sql.Timestamp, or use your own #Converter.
In general Calendar should be used in Java instead of java.util.Date, which is for the most part deprecated. Calendar also has a Timezone, so you may have similar issues.
I'm trying to save date (using C# official driver):
val = DateTime.Parse(value).Date; //Here date is {11/11/2011 12:00:00 AM}
var update = Update.Set("Date", val);
...
When I select Date from the database, the value is {11/10/2011 10:00:00 PM}
How to save only the date I want?
c# driver by default (without extra settings) saving local dates as utc date into database (date - time zone offset) but reading back without any action (so, utc date).
Because of this when you loading datetime from database you receive diff in 2 hours (your timezone offset). There are two approaches how to say to mongodb c# driver convert utc dates to local timezone dates during deserialization:
1.through the attributes for particular date field:
[BsonDateTimeOptions(Kind = DateTimeKind.Local)]
public DateTime SomeDateProperty {get;set;}
2.through global settings for all datetime fields (default is UtcInstance):
DateTimeSerializationOptions.Defaults = DateTimeSerializationOptions.LocalInstance;
Once you will do #1 or #2 you will see local date.
Update:
#2 is obsolete in latest driver version so use code below instead:
BsonSerializer.RegisterSerializer(typeof(DateTime),
new DateTimeSerializer(DateTimeSerializationOptions.LocalInstance));
Update:
#2 has changed again:
BsonSerializer.RegisterSerializer(typeof(DateTime), DateTimeSerializer.LocalInstance);
You're running into a timezone issue. Your date object is probably in a timezone other than UTC (2 hours ahead by the looks of it) or your default timezone is set to something other than UTC. The driver will convert the date to the appropriate timezone before storing it in the database.
Normally you wouldn't notice this since the reverse (retrieving the UTC date from the database) should convert it back to the original timezone. There might be an issue with the driver you're using or C# might require a bit more code to get it right.
Storing dates as strings is usually not a good idea since it disables range queries on dates.
Mongo stores everything in UTC, in case your date time is UTC this will help
val = DateTime.SpecifyKind(val , DateTimeKind.Utc);
var update = Update.Set("Date", val);
2.2.4.26 has changed again:
BsonSerializer.RegisterSerializer(typeof(DateTime), DateTimeSerializer.LocalInstance);
In my case [BsonDateTimeOptions(Kind = DateTimeKind.Local)] doesn't worked.
What i did is below
DateTime _someDateProperty ;
public DateTime SomeDateProperty
{
get { return _someDateProperty ; }
set
{
_someDateProperty = new DateTime(value.Ticks, DateTimeKind.Local);
}
}
Mongodb Date value stored in "UTC DateTime" format which comprises of both date & time. so you just cannot store date alone in the field. Instead you can get the date part alone in your application code after retrieving from mongo.
like in c#
datevalue.ToString("MM/dd/yyyy");
or
datevalue.ToShortDateString()