3

I am in need to manipulate on java.sql.Timestamp.

Input to the function is: Formatted DateTime in java.sql.Timestamp [Possible date formats are: MM/dd/yyyy hh:mm:ss aa, MM/dd/yyyy hh:mm:ss, MM/dd/yyyy hh:mm aa, MM/dd/yyyy HH:mm, MM/dd/yy hh:mm aa, MM/dd/yy HH:mm, MM/dd/yyyy, and some others]

Required Output: java.sql.Timestamp in another Timezone the same formatted DateTime as input

So basically I need to change timezone of the DateTime in java.sql.Timestamp

I have seen other posts, which mention to use JODA, but I can't use it due to some restrictions.

I have tried - to convert java.sql.Timestamp to java.date.Calendar, - then change the timezone, - then convert to it to date - format date to the same formatted datetime

See the code below:

Timestamp ts = "2012-06-20 18:22:42.0";  // I get this type of value from another function
Calendar cal = Calendar.getInstance();
cal.setTime(ts);
cal.add(Calendar.HOUR, -8);
String string = cal.getTime().toString();     // return value is in " DAY MMM dd hh:mm:ss PDT yyyy " format i.e. Wed Jun 20 10:22:42 PDT 2012
SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yyyy hh:mm:ss");  // This could be any format required
Date date;
try {
   date = formatter.parse(string);             // I am getting exception here on parsing 
} catch (ParseException e1) {
   e1.printStackTrace();
}

Can anyone tell me what is wrong here, or is there any other way to manipulate on Timezone for java.sql.Timestamp ?

Thanks.

sankethm7
  • 59
  • 1
  • 1
  • 5

5 Answers5

5

You are misunderstanding and abusing these classes.

Timestamp & Date have no time zone but UTC

manipulate on Timezone for java.sql.Timestamp

A java.sql.Timestamp is always a moment in UTC. No other time zone is involved, only UTC. Ditto for java.util.Date – always in UTC, no other time zone involved.

So your Question, as quoted above, does not make sense.

Timestamp & Date have no “format”

Neither Timestamp nor Date have a “format”. They use their own internally defined way to track the date-time. They are not strings, so they have no format. You can generate a String to represent their value in a particular format, but such a String is distinct and separate from the generating object.

java.time

You are using troublesome old date-time classes that wore supplanted years ago by the java.time classes.

Both Timestamp and Date are replaced by Instant. The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).

Your input is

String input = "2012-06-20 18:22:42.0" ;

That input is nearly compliant with standard ISO 8601 format. To comply fully, replace the SPACE in the middle with a T.

String input = "2012-06-20 18:22:42.0".replace( " " , "T" ) ;

Parse as a LocalDateTime because it lacks an indicator of offset-from-UTC or time zone.

LocalDateTime ldt = LocalDateTime.parse( input ) ;

A LocalDateTime, like your input string, does not represent a moment, is not a point on the timeline. Without the context of a time zone or offset-from-UTC, it has no real meaning. It represents only potential moments along a range of about 26-27 hours.

If you know the intended time zone, apply it to get a ZonedDateTime object.

ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = ldt.atZone( z ) ;

As for the other formats you mentioned, your Question is not at all clear. Search Stack Overflow for DateTimeFormatter class to see many examples and discussions of generating/parsing strings with the java.time classes. But first, get clear on the crucial concept that strings are not the date-time objects, and the date-time objects are not strings.

Database

If you were using java.sql.Timestamp to exchange data with a database, no need for that class anymore. As of JDBC 4.2 and later, you can directly exchange java.time objects with your database.

myPreparedStatement.setObject( … , instant ) ;

…and…

Instant instant = myResultSet.getObject( … , Instant.class ) ;

About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.

Where to obtain the java.time classes?

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
  • thank you for clarification and detailed description. FYI, Indeed this question is very old: Year 2012. at that time Java SE 7 was the latest released version. – sankethm7 Apr 09 '18 at 07:43
  • The above helped me figure out a solution: java.sql.Timestamp is a point in time of UTC. For SQL server (2008 and greater) the following can be used to return the current Timezone Offset in minutes `datepart(tzoffset,SYSDATETIMEOFFSET())` I then converted the `java.sql.Timestamp` to a Joda `DateTime` object and issued a `.plusMinutes` of the offset value returned in the sql statement. Because of Daylight savings, I returned the timezone offset on every query. – toddcscar Apr 13 '18 at 04:33
  • Neither Postgres nor Mysql don't support `Instant`. Are there drivers which do? – andreoss Jan 03 '21 at 00:16
  • @andreoss Supporting `Instant` in any JDBC driver would be utterly trivial: `OffsetDateTime#toInstant` and `Instant#atOffset( ZoneOffset.UTC )`. That why it makes no sense at all for the JDBC 4.2 team to have required support for `OffsetDateTime` but not `Instant`. – Basil Bourque Jan 03 '21 at 00:42
1

Think of Timestamp as being a fixed point in time, disconnected from where on earth you happen to be looking at a clock.

If you want to display what's on the calendar/clock for a person at that instant in a particular time zone, you can set a calendar to that time zone and then associate your SimpleDateFormat to that calendar.

For example:

public void testFormat() throws Exception {
    Calendar pacific = Calendar.getInstance(TimeZone.getTimeZone("America/Los_Angeles"));
    Calendar atlantic = Calendar.getInstance(TimeZone.getTimeZone("America/New_York"));
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
    Timestamp ts = new Timestamp(System.currentTimeMillis());
    sdf.setCalendar(pacific);
    System.out.println(sdf.format(ts));
    sdf.setCalendar(atlantic);
    System.out.println(sdf.format(ts));
}

My output was:

2012-06-25 20:27:12.506
2012-06-25 23:27:12.506
phatfingers
  • 9,770
  • 3
  • 30
  • 44
  • Hey @Phatfingers, I tried your solution, it seems that I am on right track, but the thing is I already have formatted Timestamp displaying time in UTC. I need to convert to different timezones. In your code sample, on the line sdf.setCalendar(pacific); it is not converting time to PST, because my development timezone is 'pasific'. What I need is to set that retrieved 'ts' to UTC and then convert it to different timezones; but I am not able to achieve it. Is there any way to mention that value in 'ts' is in UTC. and then convert to required timezones? – sankethm7 Jun 26 '12 at 20:51
  • The key is to treat your Timestamp as only ever representing UTC, and to treat the display of a date and time as a presentation function that incorporates time zone. Ignore the fact the Timestamp has a toString() method that uses your system's time zone. Under the hood, it's always tracking time in UTC and has no real concept of time zone built in. You don't "convert" your Timestamp to one time zone or another, rather, you format the output of the Timestamp using one time zone or another. – phatfingers Jun 27 '12 at 15:07
  • @sankethm7 if your system's time zone is PST and the native toString() output of your Timestamp is appears to be a valid UTC time, then you may have inadvertently adjusted the value of the Timestamp to be offset by 8 hours from the correct time. You wouldn't want that. – phatfingers Jun 27 '12 at 15:34
1

I got it solved, I am putting code for reference.

Timestamp ts = "2012-06-20 18:22:42.0"; // input date in Timestamp format
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
Calendar cal = Calendar.getInstance();
cal.setTime(ts)
cal.add(Calendar.HOUR,-7); // Time different between UTC and PDT is -7 hours
String convertedCal = dateFormat.format(cal.getTime());  // This String is converted datetime
 /* Now convert String formatted DateTime to Timestamp*/
SimpleDateFormat formatFrom = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
try {    
    Date date = formatFrom.parse(convertedCal);
    Timestamp finalTS = new Timestamp(date.getTime()); // Final value in Timestamp: 2012-06-20 11:22:42.0
} catch (Exception e) {
    e.printStackTrace();            
}
sankethm7
  • 59
  • 1
  • 1
  • 5
  • Please explain what you did. Now the only way is to compare code in question and answer. Also please accept the answer that you consider "solving" your problem. You can accept own answer as well. – Piro May 07 '18 at 09:48
  • For future readers, this solution doesn't take daylight savings into account or leap years. A more complete solution would use the timezone and calendar objects described in other answers. – Azeroth2b Oct 15 '21 at 15:03
0

you miss one argumment in formatter.parse http://docs.oracle.com/javase/1.4.2/docs/api/java/text/SimpleDateFormat.html#parse(java.lang.String,%20java.text.ParsePosition)

fudo
  • 219
  • 1
  • 13
Sebastian
  • 45
  • 2
  • isn't a single argument `parse` inherited from [java.text.DateFormat](http://docs.oracle.com/javase/1.4.2/docs/api/java/text/DateFormat.html#parse(java.lang.String))? – fudo Jun 25 '12 at 22:45
  • @Sebastian, I tried using parse(string, parsePosition). But it returns null. – sankethm7 Jun 26 '12 at 21:00
0

Couldn't you simply:

  1. Get original time in milliseconds
  2. Convert timezone difference to milliseconds
  3. Add or subtract the difference from the original time.
  4. Create a new timestamp using the new time in milliseconds
Jon Lin
  • 142,182
  • 29
  • 220
  • 220
namenamename
  • 195
  • 7
  • I already have formatted time in Timestamp type and it is actually UTC time. I need to convert to different timezones and return as the same format and in Timestamp type. So I don't think calculating in milliseconds is a good way to convert time in different timezones. I am keeping it as my last option. – sankethm7 Jun 26 '12 at 20:53