如何以数字格式获取当前日期和时区

How get the current date and the timezone in numbers format

我想以这种格式打印当前日期 2017/06/05 > Year/Month/Day 在它旁边,当前时区格式为 +3

我使用了这个代码

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

但是,显示是这样的:

Jun 5, 2017 | Arabia Standard Time

我想要这样:

2017/06/05 | +3

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", ""); // = +3
System.out.println(sdf.format(new Date()) + " | " + tz);

给出:

2017/06/05 | +3

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

    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


    }

我知道你在 Android,我知道 Android 上内置的是早已过时的 类,例如 DateFormatSimpleDateFormatDateCalendar。我还是要说,如果你正在做一些日期 and/or 乘以 and/or 时区的事情,你应该认真考虑跳过这些 类 并继续使用它们的现代替代品。这将需要您获得 ThreeTenABP。那么我建议这样:

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

我电脑上的结果:

2017/06/05 | +2

Asia/Kathmandu 时区的结果可能不是您想要的:

2017/06/05 | +545

您可能认为我的代码片段与使用旧的 类 相比不是很有优势。你可能会相信我的话,在很多情况下旧的 类 会给你带来负面的惊喜,所以你越早开始使用新的越好。或者,例如,您可能在格式模式字符串中输入错误,并注意您如何使用旧的 类 获得令人惊讶的结果,没有任何迹象表明有任何错误,而较新的将尝试将有意义的组合在一起错误信息。

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

正则表达式中的 (?<=\+|-) 是一个回顾:我正在用空字符串替换前面有 +-0。我徒劳地搜索了一种方法来格式化区域偏移量,如您所希望的 +3,所以我求助于 replaceFirst 方法。

进一步link:.

只是补充 , I've found another way of doing it using ThreeTenABP,但不需要替换正则表达式(虽然我不认为它更简单,下面会详细介绍)。

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

唯一的问题是 ZoneOffset 的精度为 。最小值和最大值分别为 UTC-18:00:00UTC+18:00:00。所以所有可能的值都是 UTC-18:00:00UTC-17:59:59UTC-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/05/01 | -3
2017/05/01 | +3
2017/05/01 | +10:00
2017/05/01 | +05:45


备注:

  • 我不知道有 120K 个条目的映射是否比使用正则表达式更好(由您决定)。这种方法创建了一个大地图,但至少不需要输出 post-processing(不确定这是否是一个合理的权衡)
  • 如果你想整小时偏移>=10显示为+10,+11等,只需将第一个for循环更改为for (int i = 1; i <= maxOffsetYouWant; i++) - 只是提醒 maximum possible value for maxOffsetYouWant is 18.