2013-01-10 61 views
0

我有一个GregorianCalendar问题,所以如果你愿意的话可以帮我解决它。首先我给你我的代码:java GregorianCalendar添加小时奇怪行为

private String changeClock(String day, String clock, int change) { 
    String time=""; 
    DateFormat df=new SimpleDateFormat("yyyy-MM-dd hh:mm"); 
    try { 
     Date d=df.parse(day+" "+clock); 
     GregorianCalendar g=new GregorianCalendar(); 
     g.setTime(d); 
     g.add(GregorianCalendar.HOUR_OF_DAY, change); 
     time=g.get(GregorianCalendar.YEAR)+"-" 
       +(g.get(GregorianCalendar.MONTH)+1)+"-" 
       +g.get(GregorianCalendar.DAY_OF_MONTH)+" " 
       +g.get(GregorianCalendar.HOUR_OF_DAY)+":" 
       +g.get(GregorianCalendar.MINUTE); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
    return time; 
} 

让我解释一下发生了什么。我有一个带有+和 - 按钮的GUI。当有人按下+增加一小时,或者如果按下 - 则需要一小时。

现在例如,时间是23:00,我按+,它是一切正常,它跳到第二天的00:00。问题在12:00。如果是12:00,我按+它会到1:00,然后继续。即使在2x12小时或21465x12小时后,它也不会移动到第二天。 如果我可以这样说,向后移动会好一点。当它是00:00,我按 - 它变成昨天23:00(也是日期变化)。如果我再按+,它也会改变一天(所以到今天这个例子)。

我做了什么错误,还有什么我应该写入我的代码?

感谢您的帮助球员。

+0

看起来好像你没有向我们展示你试图运行的真实代码(根据'day'和'date'来判断)。也许你可以在不需要任何GUI的情况下提取一个独立的示例,但只需要几行代码 - 首先创建一个Calendar实例,然后调用add()操作,然后检查预期的结果。 –

+0

这与您的问题无关,但无需手动构建您返回的字符串。你可以像这样简单地重用你的SimpleDateFormat对象:'return df.format(g);'。 [SimpleDateFormat](http://docs.oracle.com/javase/6/docs/api/java/text/SimpleDateFormat.html)可以同时工作:解析**和**格式。 – jahroy

+0

Grzegorz Oledzki我修复了这个日期问题。我有另一种语言,你可能不明白,所以我只是简单地换成英文。 jahroy,我知道这一点;)这只是一个例子,因为我还在做一些其他的事情,比如学习我的儿子关于编程。 – Matjaz

回答

3

您的日期格式是错误的...

您使用hh,这是的表示“小时的AM/PM(1-12)”,所以下午1点的时间了转换为凌晨1点。

您应该使用HH,它代表“每小时(0-23)”

要么,你需要提供与AM/PM标记的日期/时间格式...

无论是使用DateFormat df=new SimpleDateFormat("yyyy-MM-dd HH:mm");DateFormat df=new SimpleDateFormat("yyyy-MM-dd hh:mm a");

而不是依靠String日期/时间值,你应该传入并返回一个Date对象,请保留显示的格式。

+0

你和jahroy是对的。还没有犯这个错误,我甚至没有期待这一点。多谢你们。直到下一次。 – Matjaz

+1

+1,用于推荐传递Date对象而不是String(因为这是一个很好的答案)... – jahroy

0

TL;博士

LocalDateTime.parse( 
    "2016-01-02 12:34:56".replace(" " , "T") 
) 

使用java.time

Answer by MadProgrammer是正确的:在格式化图案使用了错误的代码。但是有一个更简单更好的方法。

您正在使用现在由java.time类取代的麻烦的旧日期时间类。

您的输入格式几乎采用标准ISO 8601格式。只需将中间的空格替换为T即可。

String input = "2016-01-02 12:34:56".replace(" " , "T"); 

java.time类默认使用ISO 8601格式。所以需要指定一个格式化模式,所以没有格式化代码出错。

LocalDateTime ldt = LocalDateTime.parse(input); 

我们解析为LocalDateTime因为输入缺少有关信息偏移从-UTC或时区。如果此值仅用于UTC,则应用偏移量以获得OffsetDateTime

OffsetDateTime odt = ldt.atOffset(ZoneOffset.UTC); 

如果适用于某个时区,则转换为ZonedDateTime

ZoneId z = ZoneId.of("America/Montreal"); 
ZonedDateTime zdt = ldt.atZone(z); 

关于java.time

java.time框架是建立在Java 8和更高版本。这些课程取代了麻烦的旧日期时间课程,如java.util.Date,.Calendar,& java.text.SimpleDateFormat

Joda-Time项目现在位于maintenance mode,建议迁移到java.time。请参阅Oracle Tutorial。并搜索堆栈溢出了很多例子和解释。

大部分的java.time功能后移植到Java 6 和ThreeTenABP还适于Android(见How to use…)。

ThreeTen-Extra项目扩展java.time与其他类。这个项目是未来可能增加java.time的一个试验场。你可以在这里找到一些有用的类,如Interval,YearWeek,YearQuarter,等等。