挂钟java_关于java:Joda-Time DateMidnight的推荐用法

LocalDate#toDateMidnight的javDoc如下:

As from v1.5, you are recommended to avoid DateMidnight and use

toDateTimeAtStartOfDay() instead because of the exception detailed

below.

This method will throw an exception if the default time zone switches

to Daylight Savings Time at midnight and this LocalDate represents

that switchover date. The problem is that there is no such time as

midnight on the required date, and as such an exception is thrown.

午夜不存在于某些时区似乎是完全避免使用DateMidnight的理由(假设您的代码没有使用已知没有这种DST情况的固定时区,并且将来不需要使用不同时区)。

但是,DateMidnight并没有被否决,JavaDoc中也没有针对DateMidnight类本身的类似建议或警告。此外,DateMidnight构造函数乐于接受一个即时和时区,这样在给定的一天中就不存在午夜,而不是像LocalDate#toDateMidnight那样抛出IllegalArgumentException。产生的DateMidnight表现得像一个DateTime,时间在一天的开始。

当某一天午夜不存在时,为什么LocalDate#toDateMidnight抛出异常而DateMidnight构造函数不存在?对于DateMidnight如果有的话,推荐的用例是什么?

请注意,"午夜"相关的类和方法在稍后对joda time 2的更新中确实被弃用了。

没有充分的理由使用DateMidnight。LocalDate是更好的选择。这是因为午夜不会在某个时区每年发生一次,会完全破坏类的可用性,并在应用程序中创建错误。

构造函数被修复以避免最坏的问题,但是看到内部毫秒值指向01:00的DateMidnight对象并不是很好。

一年一次大概一天一次?

不,我是说每年春天一次,DST从23:59跳到01:00。

哪些时区?我知道在美国,DST的变化发生在凌晨2点。

例如亚洲/加沙

天啊。我一直在想,人类发明什么比一年两次强制更换时钟更愚蠢。就是这样,在23:59:59之后换上,跳过午夜。

建议使用new datetime().withTimeAtStartOfDay()。

其实不只是推荐。所有与joda time中的"午夜"相关的类和方法都已被弃用,并解释说它们是基于错误的概念。您绝对应该使用withTimeAtStartOfDay。

或者最好直接使用LocalDate方法toDateTimeAtStartOfDay绕过DateTime对象的创建(与上述答案有关)。

new LocalDate().toDateTimeAtStartOfDay( myDateTimeZone )

DR

使用java.time类,特别是LocalDate::atStartOfDay,而不是"午夜"这一狡猾的概念。

ZoneId z = ZoneId.of("America/Montreal" );  // A time zone.

ZonedDateTime todayStart = LocalDate.now( z ).atStartOfDay( z );  // Produces a LocalDate (a whole day without time zone), then transforms into a `ZonedDateTime` (a moment on the timeline)

java.time时间

由于joda时间项目现在处于维护模式,并且团队建议迁移到java.time类,所以我将使用java.time添加示例。

如果您希望将整个一天表示为一个整体,请使用LocalDate类。LocalDate类表示没有时间和时区的仅日期值。

时区对于确定日期至关重要。在任何一个特定的时刻,日期在全球各地各不相同。例如,法国巴黎午夜几分钟后是一个新的一天,而蒙特勒魁北克仍然是"昨天"。

ZoneId z = ZoneId.of("America/Montreal" );

LocalDate today = LocalDate.now( z );

正如本页所讨论的,试图确定一天的结束是一种糟糕的做法。首先,你有一个问题,在一天的最后一秒,一个不可分割的分数。您是否解析为毫秒、微秒、纳秒或其他一些东西,因为所有这些都是常用的?而是利用新的一天的第一个时刻。

让java.time确定一天中第一个时刻的挂钟时间。不要假设时间是00:00:00,因为异常情况(如夏令时(dst))可能意味着第一个时刻是01:00:00等时间。这种DST调整目前在多个国家的时区使用。

所以,要想知道时间轴上的一个实际点,在一天开始的时候,请打电话给LocalDate::atStartOfDay。注意,这是一个比Joda Time的withTimeAtStartOfDay方法中使用的方法名的较短版本。指定ZoneId中生成ZonedDateTime对象所需/预期的时区。

ZoneId z = ZoneId.of("America/Montreal" );

ZonedDateTime zdt = today.atStartOfDay( z );

半开

那么如何表示一段时间呢?如果我想确定这一天的开始和结束,我该如何做,同时也遵循这个建议?日期时间工作中常用的解决方案是半开放式方法。在这种方法中,跨度的开始是包含的,而结束是独占的。所以"今天"是指从一天中的第一个时刻开始,一直跑到第二天的第一个时刻,但不包括第二天的第一个时刻。

ZonedDateTime zdtStartToday = LocalDate.now( z ).atStartOfDay( z );

ZonedDateTime zdtStartTomorrow = zdtStartToday.plusDays( 1 );

顺便说一下,这个额外的三个项目在这样的时间跨度内有一个方便的Interval类。

Interval todayInterval = Interval.of(

zdtStartToday.toInstant() ,

zdtStartTomorrow.toInstant()

)

关于java.time

JavaTimeFr框架是在Java 8和之后构建的。这些类取代了麻烦的旧遗留日期时间类,如java.util.Date、Calendar和SimpleDateFormat。

现在处于维护模式的joda time项目建议迁移到java.time类。

要了解更多信息,请参阅Oracle教程。以及搜索堆栈溢出以获得许多示例和解释。规格为JSR 310。

您可以直接与数据库交换java.time对象。使用符合JDBC 4.2或更高版本的JDBC驱动程序。不需要字符串,不需要java.sql.*类。

在哪里获取java.time类?

JavaSE 8、Java SE 9、Java SE 10、Java SE 11,以及后来的标准JAVA API的一部分,实现了捆绑式实现。

Java 9增加了一些次要的特性和修复。

Java SE 6和Java SE 7

大多数JavaTimeActudio的功能都被移植到TealEnter后端的Java 6和7中。

安卓

java.time类的Android包实现的更高版本。

对于早期的Android(<26),threetenabp项目适应threeten backport(如上所述)。看看如何使用三连珠……

threeten额外项目使用额外的类扩展java.time。这个项目是将来可能添加到java.time的一个试验场。您可以在这里找到一些有用的类,如Interval、YearWeek、YearQuarter等等。

这里是一个更简单的解决方案,它将检查日期时间是否在本地时间午夜发生。

private boolean isAtMidnight(org.joda.time.DateTime dateTime) {

return dateTime.toLocalDateTime().getMillisOfDay() == 0;

}

看看我的代码中的异常

Illegal instant due to time zone offset transition (daylight savings time 'gap'): 2015-03-27T00:00:00.000 (Asia/Amman)

org.joda.time.IllegalInstantException: Illegal instant due to time zone offset transition (daylight savings time 'gap'): 2015-03-27T00:00:00.000 (Asia/Amman)

现在我用

LocalDate currentDate=new LocalDate();

someMethodSetsTheDate(currentDate.toDateTimeAtStartOfDay().toDate());

而不是

someMethodSetsTheDate(new DateMidnight(date.getYear(), date.getMonthOfYear(), date.getDayOfMonth()).toDate());

现在我的建议是使用.ToDateTimeAtStartOfDay()。避免类似的例外。

请随意编辑我的答案谢谢

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
表盘式时钟,并显import java.awt.*; import java.awt.event.*; import javax.swing.*; import sun.util.calendar.Gregorian; import java.util.Calendar; import java.util.GregorianCalendar; public class Clock extends JFrame implements ActionListener{ int x, y, x0, y0, r, h, olds_x, olds_y, oldm_x, oldm_y, oldh_x, oldh_y, ss,mm,hh,old_m,old_h,ang; final double RAD = Math.PI/180; public Clock(){ super("Java时钟"); setDefaultCloseOperation(3); Image image = getToolkit().getImage("clock.gif"); setIconImage(image); setSize(200,200); setBackground(Color.black); setLocation(300,150); setResizable(false); show(); int delay = 1000; //创建一个监听事件 ActionListener drawClock = new ActionListener(){ public void actionPerformed(ActionEvent evt){ repaint(); } }; //创建一个时间计数器,每一秒触发一次 new Timer(delay,drawClock).start(); } //实现ActionListener接口必须实现的方法 public void actionPerformed(ActionEvent evt){} //绘制图形 public void paint(Graphics g){ Graphics2D g2D = (Graphics2D)g; Insets insets = getInsets(); int L = insets.left/2, T = insets.top/2; h = getSize().height; g.setColor(Color.white); //画圆 g2D.setStroke(new BasicStroke(4.0f)); g.drawOval(L+40, T+40, h-80, h-80); r = h/2 - 40; x0 = 40 + r - 5 + L; y0 = 40 + r - 5 - T; ang = 60; //绘制时钟上的12个字 for(int i = 1;i <= 12;i ++){ x = (int)((r+10)*Math.cos(RAD*ang)+x0); y = (int)((r+10)*Math.sin(RAD*ang)+y0); g.drawString(""+i, x, h-y); ang -=30; } //获得现在的时间 Calendar now = new GregorianCalendar(); int nowh = now.get(Calendar.HOUR_OF_DAY); int nowm = now.get(Calendar.MINUTE); int nows = now.get(Calendar.SECOND); String st; if(nowh < 10)st = "0"+nowh; else st = ""+nowh; if(nowm<10)st += ":0"+nowm; else st += ":"+nowm; if(nows<10)st += ":0"+nows; else st += ":"+nows; //在窗体上显示时间 g.setColor(Color.pink); g.fillRect(L, T, 50, 28); g.setColor(Color.blue); g.drawString(st,L+2,T+26); //计算时间与度数的关系 ss = 90 - nows*6; mm = 90 - nowm*
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值