3

Lets say I have a timestamp value.

Edit

Calendar curCal = new GregorianCalendar(TimeZone.getDefault());
    curCal.setTimeInMillis(System.currentTimeMillis());

    TimeZone fromTz = TimeZone.getDefault();            
    curCal.setTimeZone(fromTz);            

    TimeZone gmtTZ = TimeZone.getTimeZone("GMT");            
    Calendar toCal = new GregorianCalendar(gmtTZ);
    toCal.setTimeInMillis(curCal.getTimeInMillis());

    Date dd = toCal.getTime();
    SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy hh:mm:ss a",Locale.US);
    format.setTimeZone(gmtTZ);
    String ff = format.format(dd);

    java.sql.Timestamp curTimeInGMT = new java.sql.Timestamp(dateInLong(ff, "dd/MM/yyyy hh:mm:ss a"));

Now I am getting the milliseconds value of the above time using getTime();

Long l = t.getTime();

Definition of the getTime() method as per Java docs is Returns the number of milliseconds since January 1, 1970, 00:00:00 GMT represented by this Timestamp object.

So, from what I have understood by testing so many times, getTime() will give the milliseconds difference between the given time and January 1, 1970, 00:00:00 GMT.

For getTime() to get the difference from January 1, 1970, 00:00:00 GMT, it need another GMT time. So it needs to convert the given time to GMT time.For that conversion it needs the timezone of the given time. It will consider timezone of the given time as SYSTEM TIME ZONE and it will get the corresponding GMT time and then it will find the difference between the two GMT time and it will return the difference.

Is my understanding correct?

Matchendran
  • 333
  • 2
  • 6
  • 20
  • What you show is not a timestamp but a string representation of a timestamp... The answer all depends on how you create the actual timestamp. – assylias Jan 08 '16 at 08:19
  • For understanding I just copied timestamp value stored in the table to put it here. – Matchendran Jan 08 '16 at 08:52
  • 2
    What table? In a database table? What is the type of the database column? etc. You need to provide more information... – assylias Jan 08 '16 at 09:50
  • Reading this code fragment leaves me somewhat confused about what you want to achieve. You name the `Timestamp` variable `curTimeInGMT` - this is misleading as it is independent of any time zone. Only when you convert a time value to and from Strings a time zone comes into play because the same moment is named differently according to the relevant time zone. A similar problem mey arise when saving/retrgieving values to/from databases anbd passing them between front-end and back-end (e.g. a service) as the origin might not use the same time zone as the destination (to be elaborated). – Remigius Stalder Jan 12 '16 at 10:39

2 Answers2

2

I cannot really assess your understanding, but here's mine:

The Timestamp class inherits from Date. Date is - in line with what you quoted from the Javadoc - just a wrapper for a long value. What happens is that the String is converted (somehow - please update the codefragment if you want to share your mechanism) to a time value. This implicitly or explicitly uses a time zone, but the resulting long value is independent of a time zone, it is the same as when you would have called System.currentTimeMillis() in the time zone used in the conversion at the given time. If you want to control the time zone used for conversion, you can use a SimpleDateFormat and set the time zone as follows:

SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
simpleDateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
try {
  simpleDateFormat.parse("2016-01-08 08:03:52.0");
} catch (ParseException e) {
  // handle the error here
}

Following your edit (which is missing the definition of the function dateInLong), I have created the following test class in which I have added some console output:

public class test {
  @Test
  public void test() throws ParseException {
    Calendar curCal = new GregorianCalendar(TimeZone.getDefault());
    curCal.setTimeInMillis(System.currentTimeMillis());
    System.out.println("curCal 1:   " + curCal.getTimeInMillis());

    TimeZone fromTz = TimeZone.getDefault();
    curCal.setTimeZone(fromTz);
    System.out.println("curCal 2:   " + curCal.getTimeInMillis());

    TimeZone gmtTZ = TimeZone.getTimeZone("GMT");
    Calendar toCal = new GregorianCalendar(gmtTZ);
    toCal.setTimeInMillis(curCal.getTimeInMillis());

    Date dd = toCal.getTime();
    System.out.println("dd:         " + dd.getTime());
    SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy hh:mm:ss a", Locale.US);
    format.setTimeZone(gmtTZ);
    String ff = format.format(dd);

    long time = dateInLong(ff, "dd/MM/yyyy hh:mm:ss a");
    System.out.println("time:       " + time);
    java.sql.Timestamp curTimeInGMT = new java.sql.Timestamp(time);
    System.out.println("curTimeGMT: " + curTimeInGMT.getTime());
  }

  private long dateInLong(String dateString, String formatStr) throws ParseException {
    SimpleDateFormat format = new SimpleDateFormat(formatStr);
    return format.parse(dateString).getTime();
  }
}

It produces the following output:

curCal 1:   1452603245943
curCal 2:   1452603245943
dd:         1452603245943
time:       1452599645000
curTimeGMT: 1452599645000

As you can see, the only occasion the inner long value changes is when the date is converted to and from a String (i.e. after invoking dateInLong) namely due to the use of two different time zones (to String: GMT, from String: default - CET here). As long as you pass the inner long value around, the moment in time stays the same - regardless of whether it is wrapped by a Calendar or a descendant of Date).

Remigius Stalder
  • 1,921
  • 2
  • 26
  • 31
  • No problem, I only hope my answer helps to shed some light on the issue. – Remigius Stalder Jan 08 '16 at 08:30
  • Sorry for that timestamp value.I copied the time which is stored in the table and pasted it here to give the understanding. We are not declaring the time stamp value like that. My doubt is very simple. When we call getTime(), is it internally converting the given time to GMT time and gets the difference or it just consider the given time as GMT time and gets the difference. Because to find a difference from one GMT it needs another GMT time – Matchendran Jan 08 '16 at 08:42
  • 2
    The `getTime()` does not perform any conversion, it just returny the long vlaue. Also, there is no TZ associated with `Date` nor `TimeZone`. Again, it might be helpful if you could share how you get the `TimeZone` instance. – Remigius Stalder Jan 08 '16 at 09:42
  • I added the code for getting the timestamp object which we were discussing. Using this I'll get the current GMT time. P.S : Code not written by me. Its a code in our project – Matchendran Jan 12 '16 at 08:21
1

Two points will make this work much easier:

  • Work with date-time objects rather than strings.
    You should be using JDBC to extract java.sql.Timestamp objects from your database rather than String representations of those date-time values.
  • Use the java.time framework built into Java 8 and later.
    Avoid the old java.util.Date/.Calendar classes.

First we must either specify a formatter by which to parse your input string, or alter it to meet the ISO 8601 standard used by default in java.time. The ISO 8601 format is close to SQL format, replacing the space in the middle with a T.

String input = "2016-01-08 08:03:52.0";
String inputIso8601 = input.replace ( " ", "T" );

Parse that string as a local date-time, which means any locality. The input string lacks any time zone or offset-from-UTC info, so we start with a local and will apply an assumed time zone afterwards.

LocalDateTime localDateTime = LocalDateTime.parse ( inputIso8601 );

Let's apply the assumed time zone. I am arbitrarily choosing Montréal but obviously you need to know and use whatever time zone was intended for that string input. If you are sure that string meant UTC, use the ZoneOffset.UTC.

ZoneId zoneId = ZoneId.of ( "America/Montreal" ); // Or perhaps ZoneOffset.UTC constant.
ZonedDateTime zdt = ZonedDateTime.of ( localDateTime, zoneId );

Now we are ready to convert to a java.sql.Timestamp object, to be sent to the database. That old class has a new method, for converting to/from java.time objects. The conversion requires an Instant object which is a moment on the timeline in UTC. We can extract an Instant from our ZonedDateTime.

Instant instant = zdt.toInstant ( );
java.sql.Timestamp ts = java.sql.Timestamp.from ( instant );

Dump to console.

System.out.println ( "input: " + input + " in ISO 8601: " + inputIso8601 + " is localDateTime: " + localDateTime + " in zoneId: " + zoneId + " is zdt: " + zdt + " gives instant: " + instant + " which converts to java.sql.Timestamp ts: " + ts );

input: 2016-01-08 08:03:52.0 in ISO 8601: 2016-01-08T08:03:52.0 is localDateTime: 2016-01-08T08:03:52 in zoneId: America/Montreal is zdt: 2016-01-08T08:03:52-05:00[America/Montreal] gives instant: 2016-01-08T13:03:52Z which converts to java.sql.Timestamp ts: 2016-01-08 05:03:52.0

Read that console output carefully. Note the time-of-day on ts. This shows the unfortunate behavior of the java.sql.Timestamp method toString to silently apply the JVM’s current default time zone when generating the textual representation of the date-time value. My JVM here had a default time zone of America/Los_Angeles. So the time-of-day was adjusted (confusingly).


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.

With a JDBC driver complying with JDBC 4.2 or later, you may exchange java.time objects directly with your database. No need for strings or 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