offset time (time with time zone) in jdbc PostgreSQL - postgresql
I am trying to save and retrieve java.time.OffsetTime into PostgreSQL version 10.5, JDBC driver latest (v 42.2.5).
The Offset time is saved but with an invalid offset (it takes app server offset instead of the passed offset).
According to: https://jdbc.postgresql.org/documentation/head/8-date-time.html TIME WITH TIMEZONE is not supported (yet?).
Note that ZonedDateTime, Instant and OffsetTime / TIME [ WITHOUT
TIMEZONE ] are not supported
My question, is I want to save offset time into Postgres, so what are alternatives?
Note, I only care about time (it is actually a timetable) but I need to know the offset as well for comparing reasons with current_time.
My Example:
public class Customer {
#Id
#GeneratedValue
private Long id;
private String name;
#Column(columnDefinition = "time with time zone")
private OffsetTime serviceTime;
#Column(columnDefinition = "timestamp with time zone")
private OffsetDateTime serviceDateTime;
private Instant createdDate = Instant.now();
}
The main:
{
OffsetTime serviceTime = OffsetTime.parse("10:00+02:00");
OffsetDateTime serviceDateTime = OffsetDateTime.now().with(serviceTime);
System.out.println(serviceTime);
System.out.println(serviceDateTime);
Customer customer = new Customer().withName("wael")
.withServiceTime(serviceTime)
.withServiceDateTime(serviceDateTime);
System.out.println("customer: " + customer);
customerRepository.save(customer);
}
{
Customer dbCustomer = customerRepository.findById(1L).get();
OffsetTime dbServiceTime = dbCustomer.getServiceTime();
OffsetDateTime dbServiceDateTime = dbCustomer.getServiceDateTime();
System.out.println(dbServiceTime);
System.out.println(dbServiceDateTime);
System.out.println("from db customer: " + dbCustomer);
}
Database:
id created_date name service_date_time service_time
1 2018-10-15 10:38:27.814000 wael 2018-10-15 08:00:00.000000 10:00:00 +03:00
Output:
10:00+02:00
2018-10-15T10:00+02:00
customer: Customer(id=null, name=wael, serviceTime=10:00+02:00, serviceDateTime=2018-10-15T10:00+02:00, createdDate=2018-10-15T07:10:59.900Z)
10:00+03:00
2018-10-15T11:00+03:00
from db customer: Customer(id=1, name=wael, serviceTime=10:00+03:00, serviceDateTime=2018-10-15T11:00+03:00, createdDate=2018-10-15T07:10:59.900Z)
Note, my machine timezone is +3 (hence the printed information from db is +3), and my database server is a docker image with UTC datetime settings.
Observations:
The OffsetDatetime is saved correctly (as UTC) and retrieved correctly.
The OffsetTime is saved incorrect (it should be 10:00:00 +02:00 or 11:00:00 +03:00 or even 08:00:00 +00:00 not 10:00:00 +03:00, and retrieved incorrect!)
With JPA 2.2, you can also use OffsetTime in Postgresql.
#Column(name = "offset_time", columnDefinition = "TIME WITH TIME ZONE")
private OffsetTime offsetTime;
That's how it is stored in my database: 22:00:00.000000 +02:00
Related
How to convert date and time only at time?
I get by API such data about time and date 2021-09-05T18:16:47.790601+02:00 how can I get only hours from here?
From the API you're getting a formatted date and want to get only the hour. First, it would be better to you get from the API the UNIX date (if available) which has a timestamp format like this: https://www.unixtimestamp.com Your first question would be more either: How getting from a fromatted date a Timestamp to obtain the hour or How parsing the string to get the hour. Here the formatted method: DateTime which should help you: https://api.flutter.dev/flutter/dart-core/DateTime-class.html Here an example: final DateTime myDate = DateTime.parse('2021-09-05 18:16:47'); final int hour = myDate.hour; final int minute = myDate.minute; final int second = myDate.second; print('hour: $hour'); print('minute: $minute'); print('second: $second'); Result: hour: 18 minute: 16 second: 47 Here the parsing method: Substring which should help you: enter link description here RegExp which should help you: enter link description here Here an example: const String myDate = '2021-09-05T18:16:47.790601+02:00'; final String hour = myDate.substring(11, 13); final String minute = myDate.substring(14, 16); final String second = myDate.substring(17, 19); final String date = RegExp(r"[0-9]{2}:[0-9]{2}:[0-9]{2}").stringMatch(myDate).toString(); final List<String> splitDate = date.split(':'); print('hour: $hour'); print('minute: $minute'); print('second: $second'); print('date: $date'); print('split date: $splitDate'); Result: hour: 18 minute: 16 second: 47 date: 18:16:47 split date: [18, 16, 47]
For ISO8601 String you can convert with DateTime DateTime dt = DateTime.parse('2020-01-02 03:04:05'); then you can access what you want with dt
Spring batch - Can we read items from database using date column in a loop
I want to read data for last 30 days from database for each day.. ItemReader - Read data for each day ItemProcessor - Process data for each day ItemWriter - Write the processed data into database. I want to repeat this process till date.. public boolean processTicketStatistics() { LocalDate startDate = LocalDate.now().minus(Period.ofDays(30)); LocalDate endDate = LocalDate.now().plus(Period.ofDays(1)); for (LocalDate d = startDate; d.isBefore(endDate); d = d.plusDays(1)) { TicketStatistics statistics = new TicketStatistics(); statistics.setDate(localDateTimeToDate(d.atStartOfDay())); statistics.setTickets(ticketRepository.count(TicketSpecification.ticketHasDateRange( localDateTimeToDate(d.atStartOfDay()), localDateTimeToDate(d.atTime(LocalTime.MAX))))); ticketStatisticsRepository.save(statistics); } return true; } Can you please help me how to achieve this in Spring batch?
I would create a job that processes the data of a given day (ie the day is an identifying job parameter) and launch a job instance per day, for example: LocalDate startDate = LocalDate.now().minus(Period.ofDays(30)); LocalDate endDate = LocalDate.now().plus(Period.ofDays(1)); for (LocalDate d = startDate; d.isBefore(endDate); d = d.plusDays(1)) { JobParameters jobParameters = new JobParametersBuilder() .addDate("date", toDate(d)) // TODO implement toDate to convert LocalDate to Date .toJobParameters(); jobLauncher.run(job, jobParameters); } If the processing of each day is independent from other days (which I guess is the case), you can launch all job instances in parallel by configuring an asynchronous TaskExecutor (like a ThreadPoolTaskExecutor with a pool of 30 threads) in your JobLauncher.
Comparing dates in jpa
I am trying to find results in a postgresql database between two dates (field described in ddbb as timestamp). I have these three records which must meet target: 2016-03-04 00:00:00 2016-03-04 14:00:00 2016-03-04 10:56:00 final Calendar fechaMinima = Calendar.getInstance(); and set the parameters I want. the jpa column is defined: #Column(name = "tim_ofrecim") #NotNull #Temporal(TemporalType.TIMESTAMP) #DateTimeFormat(style = "M-") private Date Tewslofr.timOfrecim; With JPA I try to find them with the following code: #NamedQuery(name = "ofr_query2", query = "SELECT COUNT (*) FROM Tewslofr ofr " + "WHERE ofr.id.codIdprodto =:codIdprodto " + "AND ofr.codUser =:codUser " + "AND ofr.timOfrecim BETWEEN :timMinimo AND :timMaximo") public static Long getMethod(final String codProducto, final String codUser, final Calendar fechaMinima, final Calendar fechaMaxima) { return entityManager().createNamedQuery("ofr_query2", Long.class) .setParameter("codIdprodto", codProducto) .setParameter("codUser", codUser) .setParameter("timMinimo", fechaMinima, TemporalType.TIMESTAMP) .setParameter("timMaximo", fechaMaxima, TemporalType.TIMESTAMP) .getSingleResult(); } and obtain this exception: Caused by: java.lang.IllegalArgumentException: Parameter value [java.util.GregorianCalendar[time=?,areFieldsSet=false,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Europe/Paris",offset=3600000,dstSavings=3600000,useDaylight=true,transitions=184,lastRule=java.util.SimpleTimeZone[id=Europe/Paris,offset=3600000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=2,startMonth=2,startDay=-1,startDayOfWeek=1,startTime=3600000,startTimeMode=2,endMode=2,endMonth=9,endDay=-1,endDayOfWeek=1,endTime=3600000,endTimeMode=2]],firstDayOfWeek=2,minimalDaysInFirstWeek=4,ERA=1,YEAR=2016,MONTH=2,WEEK_OF_YEAR=10,WEEK_OF_MONTH=2,DAY_OF_MONTH=1,DAY_OF_YEAR=67,DAY_OF_WEEK=2,DAY_OF_WEEK_IN_MONTH=1,AM_PM=0,HOUR=8,HOUR_OF_DAY=0,MINUTE=0,SECOND=0,MILLISECOND=434,ZONE_OFFSET=3600000,DST_OFFSET=0]] was not matching type [java.util.Date] The stack trace to this is: org.springframework.dao.InvalidDataAccessApiUsageException: Parameter value [java.util.GregorianCalendar[time=?,areFieldsSet=false,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Europe/Paris",offset=3600000,dstSavings=3600000,useDaylight=true,transitions=184,lastRule=java.util.SimpleTimeZone[id=Europe/Paris,offset=3600000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=2,startMonth=2,startDay=-1,startDayOfWeek=1,startTime=3600000,startTimeMode=2,endMode=2,endMonth=9,endDay=-1,endDayOfWeek=1,endTime=3600000,endTimeMode=2]],firstDayOfWeek=2,minimalDaysInFirstWeek=4,ERA=1,YEAR=2016,MONTH=2,WEEK_OF_YEAR=10,WEEK_OF_MONTH=2,DAY_OF_MONTH=1,DAY_OF_YEAR=67,DAY_OF_WEEK=2,DAY_OF_WEEK_IN_MONTH=1,AM_PM=0,HOUR=9,HOUR_OF_DAY=0,MINUTE=0,SECOND=0,MILLISECOND=170,ZONE_OFFSET=3600000,DST_OFFSET=0]] was not matching type [java.util.Date]; nested exception is java.lang.IllegalArgumentException: Parameter value [java.util.GregorianCalendar[time=?,areFieldsSet=false,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Europe/Paris",offset=3600000,dstSavings=3600000,useDaylight=true,transitions=184,lastRule=java.util.SimpleTimeZone[id=Europe/Paris,offset=3600000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=2,startMonth=2,startDay=-1,startDayOfWeek=1,startTime=3600000,startTimeMode=2,endMode=2,endMonth=9,endDay=-1,endDayOfWeek=1,endTime=3600000,endTimeMode=2]],firstDayOfWeek=2,minimalDaysInFirstWeek=4,ERA=1,YEAR=2016,MONTH=2,WEEK_OF_YEAR=10,WEEK_OF_MONTH=2,DAY_OF_MONTH=1,DAY_OF_YEAR=67,DAY_OF_WEEK=2,DAY_OF_WEEK_IN_MONTH=1,AM_PM=0,HOUR=9,HOUR_OF_DAY=0,MINUTE=0,SECOND=0,MILLISECOND=170,ZONE_OFFSET=3600000,DST_OFFSET=0]] was not matching type [java.util.Date] at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:301) at org.springframework.orm.jpa.aspectj.JpaExceptionTranslatorAspect.ajc$afterThrowing$org_springframework_orm_jpa_aspectj_JpaExceptionTranslatorAspect$1$18a1ac9(JpaExceptionTranslatorAspect.aj:15) at com.bbva.arq.front.spring.ewsl.ofrecimientos.api.v1.domain.Tewslofr.getCuentaOfrecimientosAgente_aroundBody2(Tewslofr.java:49) at com.bbva.arq.front.spring.ewsl.ofrecimientos.api.v1.domain.Tewslofr.getCuentaOfrecimientosAgente(Tewslofr.java:1) at com.bbva.arq.front.spring.ewsl.ofrecimientos.api.v1.daos.ofrecimientos.impl.OfrecimientosDAOImpl.getMethod(OfrecimientosDAOImpl.java:52)... Caused by: java.lang.IllegalArgumentException: Parameter value [java.util.GregorianCalendar[time=?,areFieldsSet=false,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Europe/Paris",offset=3600000,dstSavings=3600000,useDaylight=true,transitions=184,lastRule=java.util.SimpleTimeZone[id=Europe/Paris,offset=3600000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=2,startMonth=2,startDay=-1,startDayOfWeek=1,startTime=3600000,startTimeMode=2,endMode=2,endMonth=9,endDay=-1,endDayOfWeek=1,endTime=3600000,endTimeMode=2]],firstDayOfWeek=2,minimalDaysInFirstWeek=4,ERA=1,YEAR=2016,MONTH=2,WEEK_OF_YEAR=10,WEEK_OF_MONTH=2,DAY_OF_MONTH=1,DAY_OF_YEAR=67,DAY_OF_WEEK=2,DAY_OF_WEEK_IN_MONTH=1,AM_PM=0,HOUR=9,HOUR_OF_DAY=0,MINUTE=0,SECOND=0,MILLISECOND=170,ZONE_OFFSET=3600000,DST_OFFSET=0]] was not matching type [java.util.Date] at org.hibernate.ejb.AbstractQueryImpl.registerParameterBinding(AbstractQueryImpl.java:360) at org.hibernate.ejb.QueryImpl.setParameter(QueryImpl.java:414) If I change to DATE instead of TIMESTAMP: public static Long getMethod(final String codProducto, final String codUser, final Calendar fechaMinima, final Calendar fechaMaxima) { return entityManager().createNamedQuery("ofr_query2", Long.class) .setParameter("codIdprodto", codProducto) .setParameter("codUser", codUser) .setParameter("timMinimo", fechaMinima.getTime(), TemporalType.DATE) .setParameter("timMaximo", fechaMaxima.getTime(), TemporalType.DATE) .getSingleResult(); } the code returns 0. Any help will be appreciated. kindest regards
I still don't know why the first option does not work, but I have made it work with the option of Date. This option was correct but was returning 0 because of de codIdprodto, not because of the dates.
How to convert date value in a facelet?
I have the rich:calendar element in a facelet: <rich:calendar value="#{listBean.to}" popup="true" datePattern="d/M/yy" cellWidth="24px" cellHeight="22px" style="width:200px"/> where listBean's defined as follows: #ManagedBean #SessionScoped public class ListBean { private Date to; //GET, SET, Others } and I need to convert the date, picked up by user to the end of a day date. I can convert it in Java as follows: Calendar date = new GregorianCalendar(); date.set(Calendar.HOUR_OF_DAY, 23); date.set(Calendar.MINUTE, 59); date.set(Calendar.SECOND, 59); date.set(Calendar.MILLISECOND, 999); to = date.getTime(); But I would not like to write those lines of code and would like to move this convertion in the facelet. Is it possible?
Entity Framework datetime vs SQL Server date
I'm using Entity Framework 4.3. In my SQL Server 2008 db, I have some dates stored as dates rather than datetime. I need to retrieve data using the date field, here a test code sample: public static Applicant Create() { var dt = new DateTime(1967, 08, 03); var r = new CrudRepo<Applicant>(UowHelper.GetUow().Context); return r.Find(a => a.DateOfBirth == dt).Single(); } However, I'm getting an issue with 'missing sequence'. Any ideas as to how I get around this? I'll also need to update the database too at some point. Thanks.
The actual result of var dt = new DateTime(1967, 08, 03); is 8/3/1967 12:00:00 AM The DataType of the DateOfBirth is Date so we need to TruncateTime the time. msdn: EntityFunctions.TruncateTime Method public static Applicant Create() { var dt = new DateTime(1967, 08, 03); var r = new CrudRepo<Applicant>(UowHelper.GetUow().Context); return r.FirstOrDefault(a => a.DateOfBirth == EntityFunctions.TruncateTime(dt)); } or remove the .Single() method instead use the .FirstOrDefault() Method
FYI, to add to spajce's answer, System.Data.Entity.Core.Objects.EntityFunctions has been deprecated to System.Data.Entity.DbFunctions