Convert Date/Time for given Timezone - java

2018-12-31 19:09发布

I want to convert this GMT time stamp to GMT+13:

2011-10-06 03:35:05

I have tried about 100 different combinations of DateFormat, TimeZone, Date, GregorianCalendar etc. to try to do this VERY basic task.

This code does what I want for the CURRENT TIME:

Calendar calendar = new GregorianCalendar(TimeZone.getTimeZone("GMT"));

DateFormat formatter = new SimpleDateFormat("dd MMM yyyy HH:mm:ss z");    
formatter.setTimeZone(TimeZone.getTimeZone("GMT+13"));  

String newZealandTime = formatter.format(calendar.getTime());

But what I want is to set the time rather then using the current time.

I found that anytime I try to set the time like this:

calendar.setTime(new Date(1317816735000L));

the local machine's TimeZone is used. Why is that? I know that when "new Date()" returns UTC+0 time so why when you set the Time in milliseconds does it no longer assume the time is in UTC?

Is possible to:

  1. Set the time on an object (Calendar/Date/TimeStamp)
  2. (Possibly) Set the TimeZone of the initial time stamp (calendar.setTimeZone(...))
  3. Format the time stamp with a new TimeZone (formatter.setTimeZone(...)))
  4. Return a string with new time zone time. (formatter.format(calendar.getTime()))

Thanks in advance for any help :D

14条回答
梦寄多情
2楼-- · 2018-12-31 19:32

The solution is actually quite simple (pure, simple Java):

System.out.println(" NZ Local Time: 2011-10-06 03:35:05");
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime localNZ = LocalDateTime.parse("2011-10-06 03:35:05",formatter);
ZonedDateTime zonedNZ = ZonedDateTime.of(localNZ,ZoneId.of("+13:00"));
LocalDateTime localUTC = zonedNZ.withZoneSameInstant(ZoneId.of("UTC")).toLocalDateTime();
System.out.println("UTC Local Time: "+localUTC.format(formatter));

OUTPUT IS:

 NZ Local Time: 2011-10-06 03:35:05
UTC Local Time: 2011-10-05 14:35:05
查看更多
忆尘夕之涩
3楼-- · 2018-12-31 19:33

We can handle this by using offset value

 public static long convertDateTimeZone(long lngDate, String fromTimeZone,
        String toTimeZone){
    TimeZone toTZ = TimeZone.getTimeZone(toTimeZone);
    Calendar toCal = Calendar.getInstance(toTZ);        

    TimeZone fromTZ = TimeZone.getTimeZone(fromTimeZone);
    Calendar fromCal = Calendar.getInstance(fromTZ);
    fromCal.setTimeInMillis(lngDate);
    toCal.setTimeInMillis(fromCal.getTimeInMillis()
            + toTZ.getOffset(fromCal.getTimeInMillis())
            - TimeZone.getDefault().getOffset(fromCal.getTimeInMillis()));      
    return toCal.getTimeInMillis();
}

Test Code snippet:

 System.out.println(new Date().getTime())
 System.out.println(convertDateTimeZone(new Date().getTime(), TimeZone
                .getDefault().getID(), "EST"));

Output: 1387353270742 1387335270742

查看更多
泛滥B
4楼-- · 2018-12-31 19:36

Understanding how computer time works is very important. With that said I agree that if an API is created to help you process computer time like real time then it should work in such a way that allows you to treat it like real time. For the most part this is the case but there are some major oversights which do need attention.

Anyway I digress!! If you have your UTC offset (better to work in UTC than GMT offsets) you can calculate the time in milliseconds and add that to your timestamp. Note that an SQL Timestamp may vary from a Java timestamp as the way the elapse from the epoch is calculated is not always the same - dependant on database technologies and also operating systems.

I would advise you to use System.currentTimeMillis() as your time stamps as these can be processed more consistently in java without worrying about converting SQL Timestamps to java Date objects etc.

To calculate your offset you can try something like this:

Long gmtTime =1317951113613L; // 2.32pm NZDT
Long timezoneAlteredTime = 0L;

if (offset != 0L) {
    int multiplier = (offset*60)*(60*1000);
    timezoneAlteredTime = gmtTime + multiplier;
} else {
    timezoneAlteredTime = gmtTime;
}

Calendar calendar = new GregorianCalendar();
calendar.setTimeInMillis(timezoneAlteredTime);

DateFormat formatter = new SimpleDateFormat("dd MMM yyyy HH:mm:ss z");

formatter.setCalendar(calendar);
formatter.setTimeZone(TimeZone.getTimeZone(timeZone));

String newZealandTime = formatter.format(calendar.getTime());

I hope this is helpful!

查看更多
春风洒进眼中
5楼-- · 2018-12-31 19:36

Had a look about and I don't think theres a timezone in Java that is GMT + 13. So I think you have to use:

Calendar calendar = Calendar.getInstance();
//OR Calendar.getInstance(TimeZone.getTimeZone("GMT"));

calendar.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY)+13);

Date d = calendar.getTime();

(If there is then change "GMT" to that Timezone and remove the 2nd line of code)

OR

SimpleDateFormat df = new SimpleDateFormat();
df.setTimeZone(TimeZone.getTimeZone("GMT+13"));
System.out.println(df.format(c.getTime()));

If you want to set a specific time/date you can also use:

    calendar.set(Calendar.DATE, 15);
calendar.set(Calendar.MONTH, 3);
calendar.set(Calendar.YEAR, 2011);
calendar.set(Calendar.HOUR_OF_DAY, 13); 
calendar.set(Calendar.MINUTE, 45);
calendar.set(Calendar.SECOND, 00);
查看更多
千与千寻千般痛.
6楼-- · 2018-12-31 19:37

Your approach works without any modification.

Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
// Timestamp for 2011-10-06 03:35:05 GMT
calendar.setTime(new Date(1317872105000L));

DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z"); 
formatter.setTimeZone(TimeZone.getTimeZone("GMT+13"));

// Prints 2011-10-06 16:35:05 GMT+13:00
System.out.println(formatter.format(calendar.getTime()));
查看更多
临风纵饮
7楼-- · 2018-12-31 19:40

Some easy way. One important thing to remember that Date does not maintain the timezone, its only long millis number, as it treated here.

/**
 * Converts source in GMT+0 to timezone specified by server
 * 
 * @throws IllegalStateException if server timezone wasnt set
 */
public static Date convertGmt(Date source)
{
    if (timeZoneServer == null)
    {
        throw new IllegalStateException("Server timezone wasnt set");
    }

    long rawOffset = timeZoneServer.getRawOffset();

    Date dest = new Date(source.getTime() + rawOffset);

    return dest;
}

/**
 * Converts source in device timezone format to GMT
 */
public static Date convertToGmt(Date source)
{
    int rawOffset = TimeZone.getDefault().getRawOffset();

    Date dest = new Date(source.getTime() - rawOffset);

    return dest;
}

TimezoneServer is something like TimeZone timeZoneServer = TimeZone.getTimeZone("GMT+1")

查看更多
登录 后发表回答