Why the time of AWST and CCT are not the same?
我编写了一个名为"dateutils"的静态类,这里有一个名为"parsedate(string)"的静态方法,它将使用一些模式将字符串转换为日期。默认时区为亚洲/上海(我在中国)
它将被传递到方法timezone.setdefault(时区);并使用simpledateformat协调字符串。匹配的模式应为"eee,dd-mmm-yyyy hh:mm:ss-zzz"这里有三个测试。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | //this one is ok. @Test public void testParseGMTDate() throws Exception { Date date = DateUtils.parseDate("Thu, 02 Aug 2016 08:12:34 GMT"); assertNotNull(date); Calendar cal = Calendar.getInstance(); cal.setTime(date); log.debug(DateUtils.format(cal.getTime())); assertEquals(cal.get(Calendar.YEAR), 2016); assertEquals(cal.get(Calendar.MONTH), 8 - 1); assertEquals(cal.get(Calendar.DATE), 2); assertEquals(cal.get(Calendar.HOUR_OF_DAY), 8 + 8); assertEquals(cal.get(Calendar.MINUTE), 12); assertEquals(cal.get(Calendar.SECOND), 34); assertEquals(DateUtils.format(cal.getTime()),"2016-08-02 16:12:34"); } // AWST is GMS+8:00 time so this one is ok. @Test public void testParseWSTDate() throws Exception { Date date = DateUtils.parseDate("Thu, 02 Aug 2016 08:12:34 AWST"); assertNotNull(date); Calendar cal = Calendar.getInstance(); cal.setTime(date); log.debug(DateUtils.format(cal.getTime())); assertEquals(cal.get(Calendar.YEAR), 2016); assertEquals(cal.get(Calendar.MONTH), 8 - 1); assertEquals(cal.get(Calendar.DATE), 2); assertEquals(cal.get(Calendar.HOUR_OF_DAY), 8); assertEquals(cal.get(Calendar.MINUTE), 12); assertEquals(cal.get(Calendar.SECOND), 34); } // junit.framework.AssertionFailedError: // Expected :9 // Actual :8 @Test public void testParseDateCCT() throws Exception { Date date = DateUtils.parseDate("Thu, 02 Aug 2016 08:12:34 CCT"); assertNotNull(date); Calendar cal = Calendar.getInstance(); cal.setTime(date); log.debug(DateUtils.format(cal.getTime())); assertEquals(cal.get(Calendar.YEAR), 2016); assertEquals(cal.get(Calendar.MONTH), 8 - 1); assertEquals(cal.get(Calendar.DATE), 2); assertEquals(cal.get(Calendar.HOUR_OF_DAY), 8); //Expected: 9 assertEquals(cal.get(Calendar.MINUTE), 12); assertEquals(cal.get(Calendar.SECOND), 34); } |
下面是一些dateutils的代码片段。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | public static final TimeZone SHA = TimeZone.getTimeZone("Asia/Shanghai"); static { Calendar calendar = Calendar.getInstance(); calendar.setTimeZone(SHA); calendar.set(2000, 0, 1, 0, 0, 0); calendar.set(MILLISECOND, 0); TWO_DIGIT_START = calendar.getTime(); } public static Date parseDate(String dateValue) { return parseDate(dateValue, null, null, SHA); } public static Date parseDate(String dateValue, String[] dateFormats, Date startDate, TimeZone timeZone) { TimeZone.setDefault(timeZone); String[] localDateFormats = dateFormats != null ? dateFormats : DEFAULT_PATTERNS; Date localStartDate = startDate != null ? startDate : TWO_DIGIT_START; String v = dateValue; if (dateValue.length() > 1 && dateValue.startsWith("\'") && dateValue.endsWith("\'")) { v = dateValue.substring(1, dateValue.length() - 1); } String[] arr = localDateFormats; int len = localDateFormats.length; for (String dateFormat : DEFAULT_PATTERNS) { // String dateFormat = arr[i]; SimpleDateFormat dateParser = DateUtils.DateFormatHolder.formatFor(dateFormat); dateParser.set2DigitYearStart(localStartDate); ParsePosition pos = new ParsePosition(0); Date result = dateParser.parse(v, pos); if (pos.getIndex() != 0) { _LOG.debug("Date parsed using: {}", dateFormat); return result; } } _LOG.error("Can't parse data: {data:{}, formats:{}, startDate:{},tz:{}}", dateValue, localDateFormats, localStartDate, TimeZone.getDefault()); return null; } |
我的问题是:根据互联网上的文档,cct&awst都是gmt+8:00时区,为什么在我的测试中,cct时间似乎是gmt+9:00。
DR
你犯了三个错误:
- 使用非标准非唯一伪时区3-4字母缩写
- 然后开始错误地假定它们的意思
- 使用过时的Java类来处理日期时间。
相反,使用适当的时区名称,格式为
所有这些都是许多程序员所犯的常见错误,从栈溢出的许多问题可以证明。
使用正确的时区名称在北美,
你用的是旧的麻烦的约会时间课程。避开它们。
JavaTimeFr框架是在Java 8和之后构建的。这些类取代了旧的麻烦的日期时间类,如
要了解更多信息,请参阅Oracle教程。以及搜索堆栈溢出以获得许多示例和解释。
Java.TimeActudio的许多功能在3TeNeN后端移植到Java 6和7,并进一步适应了Android的三层版本。
1 | Instant instant = Instant.parse ("2016-08-02T08:12:34Z" ); // 02 Aug 2016 08:12:34 |
我猜你的意思是"澳大利亚西部标准时间",由
1 2 | ZoneId zoneId_Perth = ZoneId.of ("Australia/Perth" ); ZonedDateTime zdt_Perth = instant.atZone ( zoneId_Perth ); |
对于中国,你打算用
1 2 | ZoneId zoneId_Shanghai = ZoneId.of ("Asia/Shanghai" ); ZonedDateTime zdt_Shanghai = zdt_Perth.withZoneSameInstant ( zoneId_Shanghai ); |
我不知道你的或旧的约会时间课程是什么意思。本页显示的是"科科斯群岛时间",比UTC全年提前6个半小时(无夏令时,DST)。同样,这也是为什么你不应该使用3-4个字母缩写的一个例子。
1 2 | ZoneId zoneId_Cocos = ZoneId.of ("Indian/Cocos" ); ZonedDateTime zdt_Cocos = zdt_Perth.withZoneSameInstant ( zoneId_Cocos ); |
根据一条评论,你可能是指北京时间。如果是这样,根据维基百科上的这个列表,知道北京时间在
转储到控制台。你可以看到,珀斯和上海在今年8月都比联合技术公司早了8个小时,每天16小时,而8小时(
1 | System.out.println ("instant:" + instant +" | zdt_Perth:" + zdt_Perth +" | zdt_Shanghai:" + zdt_Shanghai +" | zdt_Cocos:" + zdt_Cocos ); |
instant: 2016-08-02T08:12:34Z | zdt_Perth: 2016-08-02T16:12:34+08:00[Australia/Perth] | zdt_Shanghai: 2016-08-02T16:12:34+08:00[Asia/Shanghai] | zdt_Cocos: 2016-08-02T14:42:34+06:30[Indian/Cocos]
要以此处显示的标准ISO 8601格式以外的格式生成字符串,请使用
1 2 3 |