Reputation: 2337
I am trying to insert a value in the postgres table through Java . Column type is timestamp.
The code is like this :
SimpleDateFormat sdf= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());
String gameStartedTime = format.format(new Date());
String query= "UPDATE gameStatus g SET g.status ='" + gameStatus
+ g.gameStartTime= to_date('"
+ gameStartedTime + "','yyyy-MM-dd HH:mm:ss')"
// Doesn't matter much
+ " WHERE g.status = 'STARTED' AND " + "g.condition="+ game.getCondition();
Now when I try to execute this statement it fails I get the message like this :
ERROR: conflicting values for "mm" field in formatting string. DETAIL: This value contradicts a previous setting for the same field type.
I am not sure what is going wrong !!
Any help on this will be useful. Thanks in advance. -JE
Upvotes: 8
Views: 22489
Reputation: 340118
Column type is timestamp.
TIMESTAMP WITHOUT TIME ZONE
, otherwise known as TIMESTAMP
in Postgres, is the wrong data type for recording a moment, a point on the timeline.
👉🏽 To record a moment, you must use the type TIMESTAMP WITH TIME ZONE
as it is known both in Postgres and the SQL standard.
The difference between the two types is:
TIMESTAMP WITHOUT TIME ZONE
accepts any date and time you pass with no regard for time zone. So with a date-time of January 23, 2025 at 12:00, we have no idea if you meant noon in Tokyo Japan, noon in Toulouse France, or noon in Toledo Ohio US — three very different moments, several hours apart.TIMESTAMP WITH TIME ZONE
does account for time zone. If you pass only a date and a time, Postgres assumes you meant an offset of zero, and stores the value. If you pass an offset or time zone along with the date & time, Postgres uses that offset/zone to adjust into UTC (offset of zero), and then stores the value. The stored value is always in UTC. (Be aware some middleware/tools will unfortunately apply time zone dynamically after retrieval but before delivery to client!)The terribly-flawed date-time classes in Java have been supplanted by the modern java.time classes defined in JSR 310 and built into Java 8+.
👉🏽 Never use Date
, Calendar
, Timestamp
, SimpleDateFormat
, etc.
To capture the current moment in Java, we might use java.time.Instant
. An Instant
represents the moment as seen with an offset-from-UTC of zero hours-minutes-seconds.
Instant instant = Instant.now() ; // Current moment as seen in UTC.
java.time.OffsetDateTime
However, while JDBC 4.2 and later requires every JDBC driver to support the java.time classes, Instant
is not mapped. Instead, JDBC maps the java.time.OffsetDateTime
class to the SQL standard type TIMESTAMP WITH TIME ZONE
.
👉🏽 Capture the current moment with OffsetDateTime.now
.
OffsetDateTime odt = OffsetDateTime.now( ZoneOffset.UTC ) ;
Terms: An offset is merely a number of hours-minutes-seconds ahead/behind the temporal meridian of UTC. A time zone is a named (Continent/Region
, ex: Europe/Paris
) history of the past, present, and future changes to the offset used by the people of a particular region as decided by their politicians. The authors of the SQL standard did not understand date-time handling well, and misused the term time zone where they really meant offset.
You said:
String query= "UPDATE gameStatus g SET g.status ='" + gameStatus
+ g.gameStartTime= to_date('"
+ gameStartedTime + "','yyyy-MM-dd HH:mm:ss')"
👉🏽 Do not concatenate text like this to generate SQL. That bad habit will make you vulnerable to SQL Injection attacks. Instead, use parameters passed into a prepared statement.
And use smart objects rather than dumb strings. We have date-time objects in Java mapped to date-time types in SQL & Postgres. So do not convert in and out of text.
Modern Java now offers text blocks to ease the chore of writing SQL.
String sql = """
UPDATE order_
SET order_.when_ = ?
WHERE …
;
""" ;
…
myPreparedStatement.setObject( 1 , odt ) ;
You asked:
ERROR: conflicting values for "mm" field in formatting string
That issue is moot. You should not be manipulating text while exchanging date-time values between Java and Postgres.
Upvotes: 1
Reputation: 606
try it: ps.setTimestamp(position, new Timestamp(System.currentTimeMillis()));
Upvotes: 2
Reputation: 1586
This way works for me using current time:
String query = "INSERT INTO table1 (id,t) VALUES (?, ?)";
//update table1 set t=? where id=?
Connection con = null;
PreparedStatement ps = null;
try{
con = dataSource.getConnection();
ps = con.prepareStatement(query);
ps.setLong(1, 1234); // update ps.setLong(2, 1234);
Calendar cal = Calendar.getInstance();
Timestamp timestamp = new Timestamp(cal.getTimeInMillis());
ps.setTimestamp(2,timestamp); // ps.setTimestamp(1,timestamp);
int out = ps.executeUpdate();
if(out !=0){
System.out.println("Record saved");
}
}catch(SQLException e){
e.printStackTrace();
}finally{
try {
ps.close();
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
Or, you can establish a specific timestamp by using these lines:
Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, 2015);
cal.set(Calendar.MONTH, 0); // 0 january
cal.set(Calendar.DAY_OF_MONTH, 26);
cal.set(Calendar.HOUR_OF_DAY, 10);
cal.set(Calendar.MINUTE, 47);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
Timestamp timestamp = new Timestamp(cal.getTimeInMillis());
Upvotes: 1
Reputation: 5376
do like this.
java.sql.Date date=new Date();
Timestamp timestamp = new Timestamp(date.getTime());
this.date = timestamp;
Then add this.date
into database..
Upvotes: 2
Reputation:
mm
is always the month for the to_date()
function. There is no difference between mm
and MM
(unlike in Java's SimpleDateFormat).
You need to use mi
for the minutes.
A full list of all patterns is available in the manual: http://www.postgresql.org/docs/current/static/functions-formatting.html#FUNCTIONS-FORMATTING-DATETIME-TABLE
But you shouldn't use "dynamic" SQL in the first place. It's better to use a PreparedStatement
, java.sql.Timestamp
and setTimestamp()
instead. That relief you from any formatting problems and protect you against SQL injection.
Upvotes: 8
Reputation: 184
Try to split the date part from the query and try to compare these values.
It appears (at least from where I see) that the mm which stand for minutes,
does not comply with g.gameStartTime= to_date
.
If you pull this part outside the query you can check the values, maybe you will find what the problem is there.
Upvotes: 1