我想将此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。这是为什么?我知道当“new Date()”返回UTC + 0时间时,为什么当你设置Time以毫秒为单位时,它不再假设时间是UTC格式?
可以:
提前感谢您的帮助:D
答案 0 :(得分:35)
对我来说,最简单的方法是:
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()));
答案 1 :(得分:29)
了解计算机时间的工作原理非常重要。有了这个说我同意,如果创建一个API来帮助您像实时一样处理计算机时间,那么它应该以允许您像实时一样对待它的方式工作。在大多数情况下,情况确实存在,但有一些重要的疏忽需要引起注意。
无论如何我离题!如果您有UTC偏移(最好在UTC中工作而不是GMT偏移),您可以计算时间(以毫秒为单位)并将其添加到时间戳。请注意,SQL时间戳可能与Java时间戳不同,因为计算时间的过程并不总是相同的 - 这取决于数据库技术和操作系统。
我建议您使用System.currentTimeMillis()作为时间戳,因为这些可以在java中更一致地处理,而不必担心将SQL时间戳转换为Java Date对象等。
要计算偏移量,您可以尝试以下方法:
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());
我希望这有用!
答案 2 :(得分:22)
与往常一样,我建议您阅读this article关于Java中的日期和时间,以便您了解它。
基本思想是“引擎盖下”自从纪元以来,一切都以UTC毫秒完成。这意味着如果你在没有使用时区的情况下进行操作是最简单的,除了用户的字符串格式。
因此,我会跳过你建议的大部分步骤。
或者,您可以使用Joda time。我听说它是一个更直观的日期时间API。
答案 3 :(得分:13)
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过时的旧日期时间类。事实证明,这些旧课程很麻烦,令人困惑。避免他们。而是使用java.time类。
您的输入字符串几乎采用标准ISO 8601格式。只需用T
替换中间的SPACE即可。
String input = "2011-10-06 03:35:05".replace( " " , "T" );
LocalDateTime
现在解析为LocalDateTime
,因为输入缺少有关从UTC或时区偏移的任何信息。 LocalDateTime
没有偏移或时区的概念,因此不代表时间轴上的实际时刻。
LocalDateTime ldt = LocalDateTime.parse( input );
ZoneOffset
您似乎在说,从业务环境中您知道此字符串的意图是表示比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)等异常的一组规则。因此,我们可以指定ZoneId
到ZonedDateTime
而不是仅仅偏移量。
指定proper time zone name。切勿使用诸如EST
或IST
之类的3-4字母缩写,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。例如,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.
我强烈建议不要将日期时间值作为纪元的计数处理,例如从UTC 1970年开始的毫秒数。但如果必须,请从这样的数字创建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
(2011年10月5日星期三,格林尼治标准时间12:12:15)2011-10-06T01:12:15+13:00[Pacific/Auckland]
(2011年10月6日星期四01:12:15在新西兰奥克兰举行)。要以标准ISO 8601格式生成字符串,只需致电toString
即可。请注意ZonedDateTime
通过在方括号中附加时区名称来明智地扩展标准格式。
String output = zdt.toString();
对于其他格式,请搜索DateTimeFormatter
类的Stack Overflow。已经多次覆盖。
Locale l = new Locale( "en" , "NZ" );
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.MEDIUM ).withLocale( l );
String output = zdt.format( f );
请注意,时区 nothing 与区域设置有关。您可以使用日语和日语显示Europe/Paris
日期时间。文化规范,或葡萄牙语和巴西文化规范中显示的Asia/Kolkata
日期时间。
java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧日期时间类,例如java.util.Date
,.Calendar
和& java.text.SimpleDateFormat
。
现在位于Joda-Time的maintenance mode项目建议迁移到java.time。
要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。
大部分java.time功能都被反向移植到Java 6& ThreeTen-Backport中的7,并进一步适应Android中的ThreeTenABP(见How to use…)。
ThreeTen-Extra项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如Interval
,YearWeek
,YearQuarter
等。
答案 4 :(得分:5)
解决方案实际上非常简单(纯粹,简单的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
答案 5 :(得分:4)
看了一下,我不认为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”到该时区并删除第二行代码)
OR
SimpleDateFormat df = new SimpleDateFormat();
df.setTimeZone(TimeZone.getTimeZone("GMT+13"));
System.out.println(df.format(c.getTime()));
如果您想设置特定的时间/日期,您也可以使用:
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 :(得分:2)
java.util.Date/Calendar类很乱,应该避免使用。
更新:Joda-Time项目处于维护模式。团队建议迁移到java.time类。
以下是使用Joda-Time 2.3库的答案。很容易。
如示例代码中所述,我建议您尽可能使用命名时区,以便您的编程可以处理Daylight Saving Time(DST)和其他异常。
如果您在字符串中间放置了T
而不是空格,则可以跳过前两行代码,处理格式化程序来解析字符串。 DateTime构造函数可以采用ISO 8601格式的字符串。
// © 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
答案 7 :(得分:1)
我试过这段代码
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
答案 8 :(得分:1)
我们可以使用偏移值
来处理这个问题 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();
}
测试代码段:
System.out.println(new Date().getTime())
System.out.println(convertDateTimeZone(new Date().getTime(), TimeZone
.getDefault().getID(), "EST"));
输出: 1387353270742 1387335270742
答案 9 :(得分:1)
显示所有时区的日期和时间
import java.util.Calendar;
import java.util.TimeZone;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
static final String ISO8601 = "yyyy-MM-dd'T'HH:mm:ssZ";
DateFormat dateFormat = new SimpleDateFormat(ISO8601);
Calendar c = Calendar.getInstance();
String formattedTime;
for (String availableID : TimeZone.getAvailableIDs()) {
dateFormat.setTimeZone(TimeZone.getTimeZone(availableID));
formattedTime = dateFormat.format(c.getTime());
System.out.println(formattedTime + " " + availableID);
}
答案 10 :(得分:0)
我们可以从指定日期获得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;
}
它将根据过去的日期返回UTC时间。
我们可以像UTC时间戳一样反向到当前日期和时间(反之亦然)
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 "";
}
我希望这会对别人有所帮助。谢谢!
答案 11 :(得分:0)
快速的方法是:
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);
输出
新日期:2015-07-02T16:51:46
答案 12 :(得分:0)
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;
}
答案 13 :(得分:0)
查找具有两个不同时区的持续时间或时间间隔
import org.joda.time.{DateTime, Period, PeriodType}
val s1 = "2019-06-13T05:50:00-07:00"
val s2 = "2019-10-09T11:30:00+09:00"
val period = new Period(DateTime.parse(s1), DateTime.parse(s2), PeriodType dayTime())
period.getDays
period.getMinutes
period.getHours
输出 时间= P117DT13H40M
days = 117
minutes = 40
hours = 13
答案 14 :(得分:0)
我想提供现代的答案。
您不应该真正希望将日期和时间从GMT偏移量的字符串转换为GMT偏移量不同且格式不同的字符串。而是在程序中保留一个即时(时间点)作为适当的日期时间对象。仅在需要输出字符串时,才可以将对象格式化为所需的字符串。
解析输入
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.append(DateTimeFormatter.ISO_LOCAL_DATE)
.appendLiteral(' ')
.append(DateTimeFormatter.ISO_LOCAL_TIME)
.toFormatter();
String dateTimeString = "2011-10-06 03:35:05";
Instant instant = LocalDateTime.parse(dateTimeString, formatter)
.atOffset(ZoneOffset.UTC)
.toInstant();
在大多数情况下,Instant
是存储时间点的理想选择。如果您需要明确指出日期和时间来自格林尼治标准时间,请改用OffsetDateTime
。
转换,格式化和打印输出
ZoneId desiredZone = ZoneId.of("Pacific/Auckland");
Locale desiredeLocale = Locale.forLanguageTag("en-NZ");
DateTimeFormatter desiredFormatter = DateTimeFormatter.ofPattern(
"dd MMM uuuu HH:mm:ss OOOO", desiredeLocale);
ZonedDateTime desiredDateTime = instant.atZone(desiredZone);
String result = desiredDateTime.format(desiredFormatter);
System.out.println(result);
此打印:
2011年10月6日16:35:05 GMT + 13:00
我指定的时区为太平洋/奥克兰,而不是您提到的时差+13:00。我知道您想要新西兰的时间,而太平洋/奥克兰可以更好地告诉读者这一点。时区还考虑了夏令时(DST),因此您无需在自己的代码中考虑这一点(大多数情况下)。
由于Oct
是英语,因此最好为格式化程序提供明确的语言环境。 GMT
可能也已本地化,但我认为它只在所有语言环境中打印GMT
。
OOOO
是打印偏移量的一种方法,它可能比打印z
中的时区缩写更好,因为时区缩写通常是模棱两可的。如果您想要NZDT
(针对新西兰夏令时),只需将z
放在此处。
您的问题
我将回答有关java.time中现代类的编号问题。
可以:
- 设置对象的时间
不,现代的阶级是一成不变的。您需要从一开始就创建具有所需日期和时间的对象(这具有包括线程安全在内的许多优点)。
- (可能)设置初始时间戳记的时区
我在代码中使用的atZone
方法返回一个带有指定时区的ZonedDateTime
。其他日期时间类也有类似的方法,有时称为atZoneSameInstant
或其他名称。
- 使用新的TimeZone格式化时间戳
如图所示,使用java.time转换到新时区和格式化是两个不同的步骤。
- 返回具有新时区时间的字符串。
是,转换为所需的时区,如图所示,并设置格式为
。我发现任何时候我都尝试这样设置时间:
calendar.setTime(new Date(1317816735000L));
使用本地计算机的TimeZone。为什么会这样?
这不是您的想法,这很好地显示了旧类中的几个(很多)设计问题。
Date
没有时区。仅当您打印它时,其toString
方法会获取您的本地时区并将其用于呈现字符串。 new Date()
也是如此。在过去的25年中,这种行为使很多程序员感到困惑。Calender
已经有一个时区。 calendar.setTime(new Date(1317816735000L));
不变。Oracle tutorial: Date Time解释了如何使用java.time。
答案 15 :(得分:-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()));