转换给定时区的date/时间 – java

我想将此GMT时间戳转换为GMT + 13:

2011-10-06 03:35:05 

我已经尝试过大约100种不同的DateFormat,TimeZone,Date,GregorianCalendar等的组合来尝试做这个非常基本的任务。

这段代码做了我想要的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()); 

但我想要的是设置时间,而不是使用当前时间。

我发现任何时候我都会尝试设置这样的时间:

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

本地计算机的TimeZone被使用。 这是为什么? 我知道当“新Date()”返回UTC + 0时间,那么为什么当你设置时间以毫秒为单位时,它不再认为时间是UTC?

有可能:

  1. 在对象上设置时间(日历/date/时间戳)
  2. (可能)设置初始时间戳的时区(calendar.setTimeZone(…))
  3. 使用新的TimeZone格式化时间戳(formatter.setTimeZone(…)))
  4. 以新的时区时间返回一个string。 (formatter.format(calendar.getTime()))

预先感谢您的帮助:D

了解计算机时间如何工作非常重要。 有了这个说法,我同意如果一个API被创build来帮助你像实时一样处理计算机时间,那么它应该以这样的方式工作,使你能够像实时一样对待它。 大部分情况是这样,但有一些重要的疏忽需要注意。

无论如何,我离题! 如果你有你的UTC偏移量(最好在UTC工作比GMT偏移量),你可以计算以毫秒为单位的时间并将其添加到你的时间戳。 请注意,SQL时间戳可能与Java时间戳有所不同,因为从计算时期算起的时间并不总是相同的,这取决于数据库技术和操作系统。

我build议你使用System.currentTimeMillis()作为你的时间戳,因为这些可以在java中更一致地处理,而不必担心将SQL时间戳转换为javadate对象等。

要计算你的抵消,你可以尝试这样的事情:

 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()); 

我希望这是有帮助的!

对我来说,最简单的方法是:

 Calendar calendar = Calendar.getInstance(); calendar.setTime(new Date()); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); //Here you say to java the initial timezone. This is the secret sdf.setTimeZone(TimeZone.getTimeZone("UTC")); //Will print in UTC System.out.println(sdf.format(calendar.getTime())); //Here you set to your timezone sdf.setTimeZone(TimeZone.getDefault()); //Will print on your default Timezone System.out.println(sdf.format(calendar.getTime())); 

和往常一样,我build议阅读这篇关于Javadate和时间的文章 ,以便你理解它。

基本的想法是,在“引擎盖下”,所有事情都是在时代以来的UTC毫秒内完成的。 这意味着如果您完全不使用时区,则操作最简单,除了用户的string格式设置外。

所以我会跳过你build议的大部分步骤。

  1. 设置对象的时间(date,日历等)。
  2. 在格式化程序对象上设置时区。
  3. 从格式化程序返回一个string。

另外,你可以使用乔达时间 。 我听说这是一个更直观的date时间API。

TL;博士

 Instant.ofEpochMilli( 1_317_816_735_000L ).atZone( ZoneId.of( "Pacific/Auckland" ) ).format( DateTimeFormatter.ofLocalizedDateTime( FormatStyle.MEDIUM ).withLocale( new Locale( "en" , "NZ" ) ) ) 

…也…

 LocalDateTime.parse( "2011-10-06 03:35:05".replace( " " , "T" ) ).atZone( ZoneId.of( "Pacific/Auckland" ) ) 

java.time

问题和大多数答案使用来自最早版本的Java的过时的遗留date – 时间类。 这些老课程已被certificate是麻烦和混乱的。 避免他们。 而是使用java.time类。

ISO 8601

您的inputstring几乎是标准的ISO 8601格式。 用T代替中间的SPACE。

 String input = "2011-10-06 03:35:05".replace( " " , "T" ); 

LocalDateTime

现在parsing为LocalDateTime因为input缺less关于从UTC或时区偏移的任何信息。 LocalDateTime没有偏移量和时区的概念,所以它不代表时间轴上的实际时刻。

 LocalDateTime ldt = LocalDateTime.parse( input ); 

ZoneOffset

你似乎在说,从商业的angular度来说,你知道这个string的意图是代表一个比UTC早13个小时的时刻。 所以我们实例化一个ZoneOffset

 ZoneOffset offset = ZoneOffset.ofHours( 13 ); // 13 hours ahead of UTC, in the far east of the globe. 

OffsetDateTime

应用它来获得一个OffsetDateTime对象。 这成为时间线上的实际时刻。

 OffsetDateTime odt = ldt.atOffset( offset); 

ZoneId

但是你提到新西兰。 所以你有一个特定的时区。 时区是UTC的偏移量, 加上一组用于处理夏时制(DST)等exception的规则。 所以我们可以将ZoneId指定为ZoneId而不是单纯的偏移量。

指定一个适当的时区名称 。 切勿使用3-4字母缩写(如ESTIST因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。 例如, Pacific/Auckland

 ZoneId z = ZoneId.of( "Pacific/Auckland" ); 

ZonedDateTime

应用ZoneId

 ZonedDateTime zdt = ldt.atZone( z ); 

您可以在时间线上轻松调整到另一个区域。

 ZoneId zParis = ZoneId.of( "Europe/Paris" ); ZonedDateTime zdtParis = zdt.withZoneSameInstant( zParis ); // Same moment in time, but seen through lens of Paris wall-clock time. 

从时代计数

强烈build议不要将date时间值作为从时代开始计算的时间值,例如从UTC 1970年开始的毫秒数。 但是,如果你必须,从这样一个数字创build一个Instant

 Instant instant = Instant.ofEpochMilli( 1_317_816_735_000L ); 

然后如上所示分配一个时区,如果需要,从UTC移开。

 ZoneId z = ZoneId.of( "Pacific/Auckland" ); ZonedDateTime zdt = instant.atZone( z ); 

您的价值1_317_816_735_000L是:

  • 2011-10-05T12:12:15Z (Wed,05 Oct 2011 12:12:15 GMT)
  • 2011-10-06T01:12:15+13:00[Pacific/Auckland] (2011年10月6日星期四01:12:15在奥克兰新西兰)。

生成string

要生成标准ISO 8601格式的string,只需调用toString 。 请注意, ZonedDateTime通过在方括号中附加时区的名称明智地扩展了标准格式。

 String output = zdt.toString(); 

对于其他格式,请为DateTimeFormatter类search堆栈溢出。 已经覆盖了很多次。

指定一个FormatStyle和一个Locale

 Locale l = new Locale( "en" , "NZ" ); DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.MEDIUM ).withLocale( l ); String output = zdt.format( f ); 

关于java.time

java.time框架内置于Java 8及更高版本中。 这些类取代了麻烦的旧date时间类,如java.util.Date.Calendarjava.text.SimpleDateFormat

Joda-Time项目现在处于维护模式 ,build议迁移到java.time。

要了解更多信息,请参阅Oracle教程 。 并search堆栈溢出了很多例子和解释。

大部分的java.timefunction在ThreeTen-Backport中移植到Java 6&7中,并进一步适用于ThreeTenABP中的 Android (请参阅如何使用… )。

ThreeTen-Extra项目将java.time扩展到其他类。 这个项目是未来可能增加java.time的一个试验场。 你可能会在这里find一些有用的类,比如IntervalYearWeekYearQuarter等等。

有一个看看,我不认为这是一个时区在Java是GMT + 13的时间。所以我认为你必须使用:

 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(); 

(如果那时更改“GMT”到该时区并删除第二行代码)

要么

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

如果你想设置一个特定的时间/date,你也可以使用:

  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); 

该解决scheme实际上非常简单(纯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)); 

产量是:

  NZ Local Time: 2011-10-06 03:35:05 UTC Local Time: 2011-10-05 14:35:05 

我已经尝试这个代码

 try{ SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss Z"); Date datetime = new Date(); System.out.println("date "+sdf.format(datetime)); sdf.setTimeZone(TimeZone.getTimeZone("GMT")); System.out.println("GMT "+ sdf.format(datetime)); sdf.setTimeZone(TimeZone.getTimeZone("GMT+13")); System.out.println("GMT+13 "+ sdf.format(datetime)); sdf.setTimeZone(TimeZone.getTimeZone("UTC")); System.out.println("utc "+sdf.format(datetime)); 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()); System.out.println("using calendar "+newZealandTime); }catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } 

并得到这个结果

 date 06-10-2011 10:40:05 +0530 GMT 06-10-2011 05:10:05 +0000 // here getting 5:10:05 GMT+13 06-10-2011 06:10:05 +1300 // here getting 6:10:05 utc 06-10-2011 05:10:05 +0000 using calendar 06 Oct 2011 18:10:05 GMT+13:00 

乔达时间

java.util.Date/Calendar类是一团糟,应该避免。

更新:Joda-Time项目处于维护模式。 团队build议迁移到java.time类。

这是使用Joda-Time 2.3库的答案。 好简单。

如示例代码中所述,我build议您尽可能使用指定时区,以便编程可以处理夏令时 (DST)和其他exception情况。

如果您在string中间放置了T而不是空格,则可以跳过前两行代码,处理格式化程序以parsingstring。 DateTime构造函数可以采用ISO 8601格式的string。

 // © 2013 Basil Bourque. This source code may be used freely forever by anyone taking full responsibility for doing so. // import org.joda.time.*; // import org.joda.time.format.*; // Parse string as a date-time in UTC (no time zone offset). DateTimeFormatter formatter = org.joda.time.format.DateTimeFormat.forPattern( "yyyy-MM-dd' 'HH:mm:ss" ); DateTime dateTimeInUTC = formatter.withZoneUTC().parseDateTime( "2011-10-06 03:35:05" ); // Adjust for 13 hour offset from UTC/GMT. DateTimeZone offsetThirteen = DateTimeZone.forOffsetHours( 13 ); DateTime thirteenDateTime = dateTimeInUTC.toDateTime( offsetThirteen ); // Hard-coded offsets should be avoided. Better to use a desired time zone for handling Daylight Saving Time (DST) and other anomalies. // Time Zone list… http://joda-time.sourceforge.net/timezones.html DateTimeZone timeZoneTongatapu = DateTimeZone.forID( "Pacific/Tongatapu" ); DateTime tongatapuDateTime = dateTimeInUTC.toDateTime( timeZoneTongatapu ); 

转储这些值…

 System.out.println( "dateTimeInUTC: " + dateTimeInUTC ); System.out.println( "thirteenDateTime: " + thirteenDateTime ); System.out.println( "tongatapuDateTime: " + tongatapuDateTime ); 

当运行…

 dateTimeInUTC: 2011-10-06T03:35:05.000Z thirteenDateTime: 2011-10-06T16:35:05.000+13:00 tongatapuDateTime: 2011-10-06T16:35:05.000+13:00 

我们可以通过使用偏移值来处理

  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(); } 

testing代码片段:

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

输出:1387353270742 1387335270742

我们可以从给定的date得到UTC / GMT时间戳。

 /** * Get the time stamp in GMT/UTC by passing the valid time (dd-MM-yyyy HH:mm:ss) */ public static long getGMTTimeStampFromDate(String datetime) { long timeStamp = 0; Date localTime = new Date(); String format = "dd-MM-yyyy HH:mm:ss"; SimpleDateFormat sdfLocalFormat = new SimpleDateFormat(format); sdfLocalFormat.setTimeZone(TimeZone.getDefault()); try { localTime = (Date) sdfLocalFormat.parse(datetime); Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"), Locale.getDefault()); TimeZone tz = cal.getTimeZone(); cal.setTime(localTime); timeStamp = (localTime.getTime()/1000); Log.d("GMT TimeStamp: ", " Date TimegmtTime: " + datetime + ", GMT TimeStamp : " + localTime.getTime()); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return timeStamp; } 

它会根据传递的date返回UTC时间。

  • 我们可以像UTC时间戳那样反转到当前date和时间(反之亦然)

      public static String getLocalTimeFromGMT(long gmtTimeStamp) { try{ Calendar calendar = Calendar.getInstance(); TimeZone tz = TimeZone.getDefault(); calendar.setTimeInMillis(gmtTimeStamp * 1000); // calendar.add(Calendar.MILLISECOND, tz.getOffset(calendar.getTimeInMillis())); SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss"); Date currenTimeZone = (Date) calendar.getTime(); return sdf.format(currenTimeZone); }catch (Exception e) { } return ""; } 

我希望这会帮助别人。 谢谢!!

一个快速的方法是:

 String dateText ="Thu, 02 Jul 2015 21:51:46"; long hours = -5; // time difference between places DateTimeFormatter formatter = DateTimeFormatter.ofPattern(E, dd MMM yyyy HH:mm:ss, Locale.ENGLISH); LocalDateTime date = LocalDateTime.parse(dateText, formatter); date = date.with(date.plusHours(hours)); System.out.println("NEW DATE: "+date); 

产量

新date:2015-07-02T16:51:46

 public Timestamp convertLocalTimeToServerDatetime(String dt,String timezone){ String clientDnT = dt ;// "2017-06-01 07:20:00"; try{ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Date date = sdf.parse(clientDnT); TimeZone tz = TimeZone.getTimeZone(timezone.trim()); // get time zone of user sdf.setTimeZone(tz); // Convert to servertime zone SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); TimeZone tzInAmerica = TimeZone.getDefault(); sdf1.setTimeZone(tzInAmerica); // assign date to date String serverDate = sdf1.format(date); // Convert to servertime zone to Timestamp Date date2 = sdf.parse(serverDate); Timestamp tsm = new Timestamp(date2.getTime()); return tsm; } catch(Exception e){ System.err.println(e); } return null; } 

一些简单的方法。 一个重要的事情要记住,date不保留时区,它唯一的long millis数,因为它在这里对待。

 /** * 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就像TimeZone timeZoneServer = TimeZone.getTimeZone("GMT+1")

你的方法没有任何修改就可以工

 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()));