我们有一个应用程序,可以接受客户提供的日期时间格式。
我们最近开始迁移到Java8新的日期时间API,因为它们是线程安全的。在准备格式化程序之前,请看下面的代码,我们将A和P设置为AM
String[] AMPM = new String[2];
AMPM[0] = "A";
AMPM[1] = "P";
DateFormatSymbols dfs = new DateFormatSymbols(locale);
dfs.setAmPmStrings(AMPM);
sdf = new SimpleDateFormat(format, dfs);
但有了新的Java8日期时间API,我看不到如何定义它。但在谷歌搜索了几次之后,我发现我们必须使用DateTimeFormatterBuilder
,但这只有在我自己构建模式时才有用;这里我们从客户那里收到了完整的日期时间模式。
关于如何使用Java8做到这一点的任何提示。
您可以使用DateTimeFormatterBuilder。appendText()
方法,该方法获取带有自定义值的映射。
根据javadoc,字段AMPM_OF_DAY
可以有值0
表示AM
,1
表示PM
,因此您只需创建一个包含这些值的map并将其传递给格式化程序:
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.temporal.ChronoField;
import java.time.LocalTime;
// create map with custom values (0=AM, 1=PM, mapping to values "A" and "P")
Map<Long, String> map = new HashMap<>();
map.put(0L, "A"); // AM mapped to "A"
map.put(1L, "P"); // PM mapped to "P"
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
// hour/minute/second (change to whatever pattern you need)
.appendPattern("hh:mm:ss ")
// use the mapped values
.appendText(ChronoField.AMPM_OF_DAY, map)
// create formatter
.toFormatter();
// testing
System.out.println(formatter.format(LocalTime.of(10, 30, 45))); // 10:30:45 A
System.out.println(formatter.format(LocalTime.of(22, 30, 45))); // 10:30:45 P
输出将是:
10:30:45 A
10:30:45 P
它还可以解析字符串
:
System.out.println(LocalTime.parse("10:20:30 A", formatter)); // 10:20:30
System.out.println(LocalTime.parse("10:20:30 P", formatter)); // 22:20:30
输出将是:
10:20:30
22:20:30
如果不控制模式,可以查找字母a
(对应于AM/PM字段的模式),并用自定义版本替换它。
一种替代方法是拆分格式String
,使用a
作为分隔符,这样就不会丢失模式的其余部分:
// format with day/month/year hour:minute:second am/pm timezone
String format = "dd/MM/yyyy hh:mm:ss a z";
// split the format ("a" is the AM/PM field)
String[] formats = format.split("a");
DateTimeFormatterBuilder builder = new DateTimeFormatterBuilder()
// first part of the pattern (everything before "a")
.appendPattern(formats[0])
// use the AM/PM mapped values
.appendText(ChronoField.AMPM_OF_DAY, map);
// if there's something after the "a", add it
if (formats.length > 1) {
builder.appendPattern(formats[1]);
}
// create formatter
DateTimeFormatter formatter = builder.toFormatter();
//test
ZonedDateTime z = ZonedDateTime.of(2017, 5, 1, 10, 20, 30, 0, ZoneId.of("America/Sao_Paulo"));
// AM replaced by "A"
System.out.println(formatter.format(z)); // 01/05/2017 10:20:30 A BRT
如果a
在开头或结尾,或者即使没有a
(在这种情况下,我在结尾添加,如果不存在,我不确定是否必须添加),该算法也可以工作。
// "a" in the end
String format = "hh:mm:ss a";
DateTimeFormatter formatter = // use same code above
System.out.println(formatter.format(LocalTime.of(15, 30))); // 03:30:00 P
// "a" in the beginning
String format = "a hh:mm:ss";
DateTimeFormatter formatter = // use same code above
System.out.println(formatter.format(LocalTime.of(15, 30))); // P 03:30:00
// no "a" (field is added in the end)
String format = "HH:mm:ss";
DateTimeFormatter formatter = // use same code above
System.out.println(formatter.format(LocalTime.of(15, 30))); // 03:30:00P
你可以做一些改进,比如如果格式不包含a
,那么就不要添加它(或者在它前面添加空格),或者任何你想要的东西。
PS:此代码不处理文字('
中的文本),如"dd/MM/yyyy'at'hh: mm: ss a"
("at"是文字,不应删除/替换)。
我不是正则表达式专家(所以我不能100%确定它是否适用于所有情况),但你可以做这样的事情:
String[] formats = format.split("(?<!\'[^\']{0,20})a|a(?![^\']{0,20}\')");
此正则表达式将忽略引用文本中的a
。我必须使用{0,20}
量词,因为lookahead和lookbehinds(?模式)不接受*
,所以如果在“a”之前或之后引用的文本最多有20个字符(只需将此值更改为您认为最适合您的用例的值),这将起作用。
一些测试:
String format = "\'Time: at\' hh:mm:ss a";
DateTimeFormatter formatter = // use same code above, but with the modified regex split
System.out.println(formatter.format(LocalTime.of(15, 30))); // Time: at 03:30:00 P
String format = "dd/MM/yyyy \'at\' hh:mm:ss a z";
DateTimeFormatter formatter = // use same code above, but with the modified regex split
ZonedDateTime z = ZonedDateTime.of(2017, 5, 1, 10, 20, 30, 0, ZoneId.of("America/Sao_Paulo"));
System.out.println(formatter.format(z)); // 01/05/2017 at 10:20:30 A BRT
我得到一个变量字符串,如下所示: 上午8点45分 如果是下午,则希望将其转换为24小时制。这样我就可以放下am/pm,用它来做别的事情。 我可以像这样轻松地放弃am/pm: 当然,如果我这样做,我不知道字符串是am还是pm,所以我不知道在字符串上加上12小时,使它成为24小时。 有人知道我该如何解决这个问题吗?我绝对无法更改我得到的变量输入,它将始终是小时(在 12 小时内)、分钟和 am 或 p
问题内容: string : 2014-04-25 17:03:13 使用SimpleDateFormat足以格式化吗?否则我将转向任何新的API? 我的预期结果是(印度区域): 问题答案: 记住对象没有固有的格式,您需要两个对象来产生想要的结果-一个要解析,另一个要格式化: 输出: 请注意,在格式中使用带引号的序列(例如),它被视为格式模式中的文字。
使用SimpleDateFormat就足以格式化?否则我会转移到任何新的API? 我的预期结果是(印度区):
我想在SQL Oracle中将日期的格式更改为HH:MI:SS PM/AM格式。 我想在这样的情况下使用它: case when to\u char(a.dtime,'HH:MI:SS') 但是SQL不想显示所有to\u char时间 并且它不适用于to\u date。有什么建议吗?提前非常感谢。
问题内容: 您如何以12小时格式(AM / PM)显示JavaScript日期时间对象? 问题答案:
我在这里有我的日期来自我的API,我试图在其中解析到。我使用intl包尝试了以下方法,但我遇到了错误 未处理的异常:格式异常:尝试从 2020/07/07 09:47:54 在位置 20 读取 有人知道这里出了什么问题吗?