我的输入是2015年7月1日格式为"01-07-2015"的日期的字符串表示.我正在尝试将其解析为java.time.LocalDate变量:
final DateTimeFormatter DATE_FORMAT = DateTimeFormatter.ofPattern("dd-MM-YYYY");
final String input = "01-07-2015";
final LocalDate localDate = LocalDate.parse(input, DATE_FORMAT);
Run Code Online (Sandbox Code Playgroud)
基于DateTimeFormatterJavaDoc,我希望这可行.但是,我收到了一条非常友好和乐于助人的消息:
引起:java.time.DateTimeException:无法从TemporalAccessor获取LocalDate:{DayOfMonth = 1,MonthOfYear = 7,WeekBasedYear [WeekFields [MONDAY,4]] = 2015},ISO类型为java.time.format.Parsed
我真的不明白这个异常告诉我的是什么.任何人都可以解释我出了什么问题吗?
我需要为很多用户安排定期工作.此作业将以固定速率运行,间隔时间.我希望在该时间间隔内统一分配每个用户的作业执行.例如,如果间隔是4天,我将使用一致的散列函数和每个用户的标识符来同时安排作业,例如.每隔4天,第3天.
间隔是相对于所有用户都相同的原始时刻.给定这样的原点瞬间,像Instant#EPOCH或其他一些常数值,如何找到当前间隔的开始日期?
我可以
Instant now = Instant.now();
Instant origin = Instant.EPOCH;
Duration interval = Duration.ofDays(4);
Duration duration = Duration.between(origin, now);
long sinceOrigin = duration.toMillis();
long millisPerInterval = interval.toMillis();
long intervalsSince = sinceOrigin / millisPerInterval;
Instant startNext = origin.plus(interval.multipliedBy(intervalsSince));
int cursor = distributionStrategy.distribute(hashCode, millisPerInterval);
Run Code Online (Sandbox Code Playgroud)
然后我可以使用它cursor来调度Instant相对于当前间隔开始的作业.
这里有很多数学,我不确定在任何地方转换到毫秒都会维持实际日期.是否有更精确的方法来划分两个时刻之间的时间并找到我们目前所处的那一个(细分)?
在DateTimeFormatter类文件说,有关当年的格式代码:
你在2004年; 04
y年的2004年; 04
...
年份:字母数决定了使用填充的最小字段宽度.如果字母数是2,则使用减少的两位数形式.对于打印,这将输出最右边的两位数字.对于解析,这将使用2000的基值进行解析,从而产生2000到2099(包括2000和2099)范围内的一年.如果字母数小于4(但不是2),则符号仅按负号年份输出,符合SignStyle.NORMAL.否则,如果超出了焊盘宽度,则根据SignStyle.EXCEEDS_PAD输出符号.
没有提到"时代".
那么究竟是什么这两个代码之间的差异,u对y,year对year-of-era?
什么时候应该使用类似这种模式的东西uuuu-MM-dd以及何时yyyy-MM-dd使用Java中的日期?
似乎那些知道使用的代码编写的示例代码uuuu,但为什么呢?
其他格式化类如遗产SimpleDateFormat只有yyyy,所以我很困惑为什么java.time uuuu为"年代" 带来了这个.
我正在使用Java 8中的新java.time包.我有一个遗留数据库,它给了我java.util.Date,我转换为Instant.
我想要做的是添加一段基于另一个数据库标志的时间.我可以添加几天,几周,几个月或几年.我不想关心我要添加的内容,我希望将来能够添加更多选项.
我的第一个想法是Instant.plus(),但这给了我一个UnsupportedTemporalTypeException超过一天的价值.Instant显然不支持大单位时间的操作.好的,无论如何LocalDateTime.
所以这给了我这个代码:
private Date adjustDate(Date myDate, TemporalUnit unit){
Instant instant = myDate.toInstant();
LocalDateTime dateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
dateTime = dateTime.plus(1, unit);
Instant updatedInstant = dateTime.atZone(ZoneId.systemDefault()).toInstant();
return new Date(dueInstant.toEpochMilli());
}
Run Code Online (Sandbox Code Playgroud)
现在,这是我第一次使用新的时间API,所以我可能在这里错过了一些东西.但是我必须离开这似乎很笨重:
Date --> Instant --> LocalDateTime --> do stuff--> Instant --> Date.
Run Code Online (Sandbox Code Playgroud)
即使我不必使用Date部分,我仍然认为它有点尴尬.所以我的问题是,我这样做完全错了,最好的办法是什么?
编辑:扩展评论中的讨论.
我想我现在更好地了解了LocalDateTime和Instant如何使用java.util.Date和java.sql.Timestamp.感谢大家.
现在,更实际的考虑.假设用户向我发送了他们在世界任何地方的日期,任意时区.他们发给我2014-04-16T13:00:00我可以解析的LocalDateTime.然后我将它直接转换为java.sql.Timestamp并在我的数据库中保留.
现在,我没有做任何其他事情,我从我的数据库中提取我的java.sql.timestamp,转换为LocalDateTime使用timestamp.toLocalDateTime().都好.然后我使用ISO_DATE_TIME格式将此值返回给我的用户.结果是2014-04-16T09:00:00.
我认为这种差异是因为某种类型的隐式转换到/来自UTC.我认为我的默认时区可能会应用于该值(EDT,UTC-4),这可以解释为什么数字关闭4小时.
新问题.从本地时间到UTC的隐式转换在哪里?保留时区的更好方法是什么.我不应该直接从当地时间作为字符串(2014-04-16T13:00:00)来LocalDateTime?我应该期待用户输入的时区吗?
我知道JAXB(用于XML绑定的Java体系结构)可以编组/解组java.util.Date对象,如Blaise Doughan的回答所示.
但有关新东西java.time包中的对象的Java 8,如ZonedDateTime?JAXB是否已更新以处理这种新的内置数据类型?
我注意到java.time.format.DateTimeFormatter无法按预期解析.见下文:
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
public class Play {
public static void tryParse(String d,String f) {
try {
LocalDate.parse(d, DateTimeFormatter.ofPattern(f));
System.out.println("Pass");
} catch (Exception x) {System.out.println("Fail");}
}
public static void main(String[] args) {
tryParse("26-may-2015","dd-L-yyyy");
tryParse("26-May-2015","dd-L-yyyy");
tryParse("26-may-2015","dd-LLL-yyyy");
tryParse("26-May-2015","dd-LLL-yyyy");
tryParse("26-may-2015","dd-M-yyyy");
tryParse("26-May-2015","dd-M-yyyy");
tryParse("26-may-2015","dd-MMM-yyyy");
tryParse("26-May-2015","dd-MMM-yyyy");
}
}
Run Code Online (Sandbox Code Playgroud)
只有最后一次尝试tryParse("26-May-2015","dd-MMM-yyyy");将"通过".根据文档LLL应该能够解析出文本格式.也不是大写'M'与小写'm'的细微差别.
这真的很烦人,因为我无法默认解析Oracle DB默认格式化的字符串
SELECT TO_DATE(SYSDATE,'DD-MON-YYYY') AS dt FROM DUAL;
Run Code Online (Sandbox Code Playgroud)
同样,对于以下程序:
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
public class Play {
public static void output(String f) {
LocalDate d = LocalDate.now();
Locale l = …Run Code Online (Sandbox Code Playgroud) 我试图在Java 8中检查日期是否超过10年且超过20年.我使用Date.before()And Date.after()并且经过currentDate-10多年和currentDate-20岁月作为论据.
有人可以建议什么是最简单的方法来获取日期格式为10年和20年的日期格式,以传递给我before()和after()方法?
默认的java.time.Clock实现基于System.currentTimeMillis().正如这里所讨论的那样, 单调增加Java的时间?,不保证是单调的.
事实上,我经常遇到一种情况,系统时间会自动调整到过去几秒钟,而java时钟也会跳回来.
//now() returns 2016-01-13T22:34:05.681Z
order.setCreationTime(Instant.now());
//... something happens, order gets cancelled
//now() returns 2016-01-13T22:34:03.123Z
//which is a few seconds before the former one,
//even though the call was performed later - in any reasonable sense.
//The recorded history of events is obviously inconsistent with the real world.
order.setCancelationTime(Instant.now());
Run Code Online (Sandbox Code Playgroud)
然后,当人们不能仅依靠一个方向的时间时,就不可能执行时间敏感的事情,例如记录和分析事件历史.
上述帖子说System.nanoTime()是单调的(如果底层系统支持它).所以,如果我想将我的代码基于java.time API,我需要内部使用nanoTime的Clock来确保单向流动的时间.也许这样的事情会起作用.或者不是吗?
public class MyClock() extends java.time.Clock {
private final long adjustment;
public MyClock() {
long cpuTimeMillis = System.nanoTime()/1000000;
long systemTimeMillis = …Run Code Online (Sandbox Code Playgroud) 是否有更好/更简单的方法来构建LocalDateTime今天早上6点的对象?
LocalDateTime todayAt6 = LocalDateTime.now().withHour(6).withMinute(0).withSecond(0).withNano(0);
Run Code Online (Sandbox Code Playgroud)
不知怎的,我不喜欢处理分钟/秒/纳米时我想说的是now().withHours().
我一直在Java EE应用程序中使用Joda Time进行日期时间操作,其中关联客户端提交的日期时间的字符串表示已使用以下转换例程转换,然后将其提交到数据库,即在getAsObject()方法中. JSF转换器.
org.joda.time.format.DateTimeFormatter formatter = org.joda.time.format.DateTimeFormat.forPattern("dd-MMM-yyyy hh:mm:ss a Z").withZone(DateTimeZone.UTC);
DateTime dateTime = formatter.parseDateTime("05-Jan-2016 03:04:44 PM +0530");
System.out.println(formatter.print(dateTime));
Run Code Online (Sandbox Code Playgroud)
当地时区比UTC/ 提前5小时30分钟GMT.因此,转换为UTC应从使用Joda Time正确发生的日期时间中扣除5小时30分钟.它按预期显示以下输出.
05-Jan-2016 09:34:44 AM +0000
Run Code Online (Sandbox Code Playgroud)
► 已+0530取代时区偏移量,+05:30因为它取决于<p:calendar>以此格式提交区域偏移量.似乎不可能改变这种行为<p:calendar>(否则本身就不需要这个问题).
但是,如果尝试在Java 8中使用Java Time API,那么同样的事情就会被破坏.
java.time.format.DateTimeFormatter formatter = java.time.format.DateTimeFormatter.ofPattern("dd-MMM-yyyy hh:mm:ss a Z").withZone(ZoneOffset.UTC);
ZonedDateTime dateTime = ZonedDateTime.parse("05-Jan-2016 03:04:44 PM +0530", formatter);
System.out.println(formatter.format(dateTime));
Run Code Online (Sandbox Code Playgroud)
它意外地显示以下错误输出.
05-Jan-2016 03:04:44 PM +0000
Run Code Online (Sandbox Code Playgroud)
显然,转换的日期时间不符合UTC它应该转换的日期时间.
它需要采用以下更改才能正常工作.
java.time.format.DateTimeFormatter formatter = java.time.format.DateTimeFormatter.ofPattern("dd-MMM-yyyy hh:mm:ss a z").withZone(ZoneOffset.UTC); …Run Code Online (Sandbox Code Playgroud)