生成&;解析";“年-月”;Java文本中的值
我有一个HTML弹出菜单,列出了各种年-月组合。每个菜单项都有一个本地化的字符串表示形式,如内容显示的生成&;解析";“年-月”;Java文本中的值,java,parsing,datetime,Java,Parsing,Datetime,我有一个HTML弹出菜单,列出了各种年-月组合。每个菜单项都有一个本地化的字符串表示形式,如内容显示的2015年11月,以及一个编码值属性,如201511 例如: 2015年11月 2015年10月 2015年9月 我使用java.util.Calendar生成编码值字符串 int month = Calendar.getInstance().get(Calendar.MONTH)+1; int year = Calendar.getInstance().get(Calendar.YEAR)
2015年11月
,以及一个编码值属性,如201511
例如:
2015年11月
2015年10月
2015年9月
我使用java.util.Calendar生成编码值字符串
int month = Calendar.getInstance().get(Calendar.MONTH)+1;
int year = Calendar.getInstance().get(Calendar.YEAR);
String v = String.valueOf( year ) + String.valueOf( month );
这是可行的,但使用日历(日期加上一天中的某个时间)似乎很奇怪,而我真正关心的是没有日期或时间的年+月
在现代Java中有更好的方法来处理年+月吗?事实上,在现代Java中有更优雅的方法来处理年+月,Java 8和更高版本中内置了Java.time框架 此外,您的示例代码还存在一些其他问题:
- 两次获取当前时刻。
重复获取当前时刻两次是不好的做法。如果这两行代码恰好发生在午夜钟声前后,您将使用两个不同的日期,可能是两个不同的月份甚至年份李> - 忽略时区问题。下面讨论
YearMonth
新类包括一个类,完全是为了您的目的:表示一年+一个月,没有任何日期、时间或时区
我建议在业务逻辑中使用此类对象,仅在必要时使用字符串,例如生成HTML
时区
虽然一个年月内不包括时区,但请注意,时区对于确定当前的年月至关重要。目前的日期,也就是年月,在世界各地随时都在变化。东方的巴黎比西方的蒙特勒尔(Montréal)更早地迎来了新的一天,那里仍然是“昨天”
如果在示例代码中省略了时区,则会隐式使用JVM的当前默认时区。这种隐式使用意味着您的结果可能会因以下任何原因而有所不同:您的代码可能会移动到另一台计算机,系统管理员可能会更改主机的默认值,甚至更糟糕的是,在同一JVM中运行的任何应用程序的任何线程中的任何代码都可能会更改。最好指定所需/预期的时区(在java.time中)
字符串格式
java.time类中的toString
方法默认使用标准格式。您的格式,YYYYMM
与标准格式类似,但在这种特殊情况下(年-月),需要连字符以避免歧义,YYYY-MM
。大多数标准格式允许省略连字符的“基本”变体,但此处不允许
我强烈建议尽可能将日期时间值的字符串表示形式设置为ISO8601格式
String output = yearMonth.toString ();
2015-12
我强烈建议在HTML属性中使用这种格式。坚持ISO 8601将简化您的生活。如下所示(请注意连字符):
201512
本地化字符串
让java.time完成显示文本的本地化工作。请注意,该语言被传递给DateTimeFormatter,而不是隐式地依赖于JVM的当前默认语言环境
Locale locale = Locale.CANADA_FRENCH;
DateTimeFormatter formatter = DateTimeFormatter.ofPattern ( "MMM yyyy" , locale );
String output = yearMonth.format ( formatter );
déc。2015年
日期
如果需要特定日期,请指定要与本年和本月合并的月份中的某一天
LocalDate ld = ym.atDay( 1 ) ; // Get first day of that year-month.
从那里你可以得到一个特定的时刻,比如一天中的第一个时刻。不要假设一天从00:00:00开始。让java.time确定第一个时刻
ZoneId z = ZoneId.of( "Pacific/Auckland" ) ;
ZonedDateTime zdt = ld.atStartOfDay( z ) ;
如果您需要在UTC中查看相同的时刻,请提取一个瞬间
Instant instant = zdt.toInstant() ;
仅供参考,我以中使用的示例代码为基础,重点不同。哇!我不知道这种在堆栈上发布问题的方法!这是合法的权利吗?@Identity1是的,如果这是你的意思,这是合法的,甚至是鼓励的。如果您的意思是从另一个问题中提取代码片段,那么这是不寻常的。事实上,我确实在下面写下了关于原始问题的答案,但后来意识到我的答案所涉及的问题超出了原始作者的意图。这个问题与我的回答无关。所以,我想说,是的,这是合法的。我在这里的目的是明确地关注
YearMonth
类。这很酷!我想我可以用这种方法
LocalDate ld = ym.atDay( 1 ) ; // Get first day of that year-month.
ZoneId z = ZoneId.of( "Pacific/Auckland" ) ;
ZonedDateTime zdt = ld.atStartOfDay( z ) ;
Instant instant = zdt.toInstant() ;