2017-06-05 125 views
3

我要打印的当前日期这种格式2017/06/05>Year/Month/Day 在它的旁边,这种格式+3如何获取当前日期和数字格式的时区

我用这个代码当前时区

String DateToday = DateFormat.getDateInstance().format(new Date()); 
String TZtoday = DateFormat.getTimeInstance().getTimeZone().getDisplayName(); 
txt.setText(DateToday + " | "+ TZtoday); 

但是,它这样表示:

2017年6月5日|阿拉伯标准时间

我希望它是这样的:

2017年6月5日| +3

+1

如果偏移量不是整小时数,您希望发生什么? –

+0

@ OleV.V。没有得到什么意思呢? –

+1

例如,假设“Asia/Kathmandu”的区域偏移量为+05:45。这应该如何打印?如果答案是“不关心”,我建议你在这种情况下抛出异常。 –

回答

2
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd | X"); 
System.out.println(sdf.format(new Date())); 

靠拢,但时区印有前导零:

2017/06/05 | +03 

我想你可以从时间区域中删除前导零,如果你需要:

SimpleDateFormat date = new SimpleDateFormat("yyyy/MM/dd"); 
SimpleDateFormat zone = new SimpleDateFormat("ZZZZZ"); // = +03:00 
String tz = zone.format(new Date()).split(":")[0] 
    .replaceAll("^(\\+|-)0", "$1"); // = +3 
System.out.println(sdf.format(new Date()) + " | " + tz); 

这给:

2017/06/05 | +3 
+0

日期显示正确:D,但只有当我在格式中移除X时才会显示错误,因为它会以错误java.lang的形式崩溃应用程序。IllegalArgumentException:未知模式字符'X'' –

+0

@Sam您正在使用java.text.SimpleDateFormat吗?也许'X'是在Java 8中添加的。不,我刚刚检查过,它也在Java 7中。 –

+0

@Sam根据[Android文档](https://developer.android.com/reference/java/text/SimpleDateFormat.html),它也支持Android。你在用什么? –

0

使用以下逻辑来获取所需的日期格式。

public static void main(String[] args) { 

     Calendar cal = Calendar.getInstance(); 
     cal.add(Calendar.DATE, 1); 
     SimpleDateFormat format1 = new SimpleDateFormat("yyyy-MM-dd"); 
     System.out.println(cal.getTime()); 
// Output "Wed Sep 26 14:23:28 EST 2012" 

     String formatted = format1.format(cal.getTime()); 
     String formattedmain=formatted.replace("-","/"); 
     System.out.println(formatted); 
     // Output "2012-09-26" 
     System.out.println(formattedmain); 

//Output :- 2017/06/06 


    } 
+2

这是错误的格式。 OP询问斜杠,而不是破折号和时区偏移量。 –

+0

等待我会根据需要做斜线修改,这不是什么大问题 –

+0

而对于偏移量,在这里添加b的时间量cal.add(Calendar.DATE,1);在这个瞬间1给出1天的偏移量在那里。 –

3

我知道你是在Android上,我知道那是什么提供在Android内置就像DateFormatSimpleDateFormatDateCalendar的早已过时的类。但我仍然说,如果你正在做日期和/或时间和/或时区的事情,你应该认真考虑跳过这些课程并转向他们的现代替代品。这将要求你得到ThreeTenABP。那么我建议是这样的:

2017/06/05 | +2 

结果在亚洲/加德满都时区可能不正是你想要的东西:我的电脑上

ZonedDateTime date = ZonedDateTime.now(ZoneId.systemDefault()); 
    String tzToday = date.format(DateTimeFormatter.ofPattern("uuuu/MM/dd | x")); 
    tzToday = tzToday.replaceFirst("(?<=\\+|-)0", ""); 

结果

2017/06/05 | +545 

你可能会认为我的代码片段并不比使用旧的类更有优势。当我说有这么多的老班给你带来负面的惊喜时,你可能会说我的话,所以你可以越早开始使用新的,越好。或者,你可能会在格式模式字符串中输入一个拼写错误,例如,注意你如何得到一个令人惊讶的结果,而没有发现任何错误的迹象,而新的类将尝试将一个有意义的错误信息放在一起。

需要注意的另一个细节是我正在读取系统时钟和JVM的时区一次(将时区传递回now()以确保它在该时间使用)。您的代码在问题中首先格式化日期,然后读取时区。如果有人在两者之间更改时区,则结果将不一致。非常不可能,但这也意味着很难有人能够弄清楚发生了什么。

正则表达式中的(?<=\\+|-)是一个倒序:我将用+-替换0,后面带有空字符串。我徒劳地搜索一种方法来根据需要格式化区域偏移量,如+3,所以我使用了replaceFirst方法。

更多链接:How to use ThreeTenABP in Android Project

+2

好吧,我在转移到Android之前一直是一个java开发人员,所以我会确保我的下一次Times/Dates实现将与ThreeTenABP一起使用,非常感谢建议。! –

1

作为@Ole V.V.'s answer的补充,我发现了另一种使用ThreeTenABP的方法,但不需要正则表达式替换(尽管我不认为它更简单,下面更多)。

使用DateTimeFormatterBuilder可以使用HashMap将偏移值映射到String。因此,对于整个抵消时间(如+03:00),可以将相应的值映射到字符串+3等等。

唯一的问题是,ZoneOffset精度。最小值和最大值分别为UTC-18:00:00UTC+18:00:00。所以所有可能的值是UTC-18:00:00,UTC-17:59:59,UTC-17:59:58等等。格式化程序需要映射所有可能的值(否则它将显示偏移量的秒数值),因此地图将会有超过120K个条目!

为了建立这个地图,我做了2个循环:

  • 第一个循环映射整个小时的偏移量(+01:00+1-02:00-2等)
  • 第二个循环的所有映射其它值(它们保持不变):
    • 整个小时> = 10(如+10:00
    • 未整小时(如+05:30

的代码来创建格式化:

// builds a hashmap to map all offset values 
Map<Long, String> map = new HashMap<>(); 

// First loop: Map whole hours from 1 to 9 and from -9 to -1 
// So a "+01:00" offset is displayed as "+1" 
for (int i = 1; i <= 9; i++) { 
    long seconds = ZoneOffset.ofHours(i).getTotalSeconds(); 
    // 1 hour offset maps to "+1" and so on 
    map.put(seconds, "+" + i); 
    // -1 hour offset maps to "-1" and so on 
    map.put(-seconds, "-" + i); 
} 

// second loop: Need to map all other possible values for not-whole hours 
// offsets like "+10:00" and "+01:30" are not changed 
int minOffset = ZoneOffset.MIN.getTotalSeconds(); 
int maxOffset = ZoneOffset.MAX.getTotalSeconds(); 
for (long i = minOffset; i <= maxOffset; i++) { 
    // the map already contains whole hours, don't need to overwrite the values 
    if (!map.containsKey(i)) { 
     // uses default String representation (like "+05:30") 
     map.put(i, ZoneOffset.ofTotalSeconds((int) i).getId()); 
    } 
} 

// create the formatter 
DateTimeFormatter formatter = new DateTimeFormatterBuilder() 
       // year/month/day and the "|" 
       .appendPattern("uuuu/MM/dd | ") 
       // use the map of custom values (offset will use the values in the map) 
       .appendText(ChronoField.OFFSET_SECONDS, map) 
       // create formatter 
       .toFormatter(); 

一些测试:

LocalDateTime dt = LocalDateTime.of(2017, 5, 1, 10, 0); 
ZonedDateTime z = ZonedDateTime.of(dt, ZoneId.of("America/Sao_Paulo")); // UTC-03:00 
System.out.println(formatter.format(z)); // 2017/05/01 | -3 

// just picking some timezone in Arabia Stardard Time 
// (there are more than one timezone in AST: https://en.wikipedia.org/wiki/UTC%2B03:00#Arabia_Standard_Time) 
// I don't know in which one you are 
z = ZonedDateTime.of(dt, ZoneId.of("Asia/Qatar")); // UTC+03:00 
System.out.println(formatter.format(z)); // 2017/05/01 | +3 

// 2-digit offset 
z = ZonedDateTime.of(dt, ZoneId.of("Asia/Vladivostok")); // UTC+10:00 
System.out.println(formatter.format(z)); // 2017/05/01 | +10:00 

// not whole hour 
z = ZonedDateTime.of(dt, ZoneId.of("Asia/Kathmandu")); // UTC+05:45 
System.out.println(formatter.format(z)); // 2017/05/01 | +05:45 

的输出是:

2017年5月1日| -3
2017/05/01 | +3
2017/05/01 | +10:00
2017/05/01 | +05:45


注:

  • 我不知道是否有120K条目地图比使用正则表达式(这是由你来决定)更好。这种方法创建一个大的地图,但至少不需要输出后处理(不知道这是否合理取舍)
  • 如果要将整小时偏移> = 10显示为+10+11和依此类推,只需将第一个for循环更改为for (int i = 1; i <= maxOffsetYouWant; i++) - 只需提醒maximum possible value for maxOffsetYouWant is 18即可。
+1

哇,这是一个非常有趣的方法来解决这个问题,谢谢你,尽管对我来说完全理解起来更加复杂。所以现在我会坚持旧的Java类解决方案,因为我的应用程序的受众不会超过+3时区。但再次感谢您的帮助 –

+0

事实上,我必须承认,针对这一特定案例的解决方案比我想要的更复杂。但除此之外,你应该花一些时间学习新的API。它比'Date'和'Calendar'好得多,它真的值得学习。 – 2017-06-06 11:48:00

+1

我肯定;) –

相关问题