Question

I have a problem with GregorianCalendar so if you please can help me out with it. First I'll give you my code:

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;
}

Let me explain what is happening. I have a GUI with + and - button. When someone press + it add one hour, or if - is pressed then take one hour.

Now example, time is 23:00 and I press +, it is everything ok and it jumps to 00:00 of the next day. Problems are on 12:00. If it is 12:00 and I press + it goes to 1:00 and that goes on and on. It doesn't move to the next day even after 2x12 hours or 21465x12 hours. Moving backward is a little better if I can say so. When it is 00:00 and I press - it changes to yesterday 23:00 (also date changes). If I then press + it changes also one day forward (so to today in this case).

What have I done wrong or what more should I write to my code?

Thanks for your help guys.

Was it helpful?

Solution

Your date format is wrong...

You're using hh, which is a representation of the "Hour in am/pm (1-12)", so a time of 1pm is been converted to 1am instead.

You should be using HH which is a a representation of the "Hour in day (0-23)".

Either that, or you need supply a date/time format with the am/pm marker...

Using either DateFormat df=new SimpleDateFormat("yyyy-MM-dd HH:mm"); or DateFormat df=new SimpleDateFormat("yyyy-MM-dd hh:mm a");

Instead of relying on String date/time values, you should be passing in and back a Date object, leave the formatting for the display.

OTHER TIPS

tl;dr

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

Using java.time

The Answer by MadProgrammer is correct: Wrong code used in formatting pattern. But there is an even easier and better approach.

You are using troublesome old date-time classes now supplanted by the java.time classes.

Your input format in almost in standard ISO 8601 format. Just replace the SPACE in middle with a T.

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

The java.time classe use ISO 8601 formats by default. So need to specify a formatting pattern at all, so no formatting codes to get wrong.

LocalDateTime ldt = LocalDateTime.parse( input );

We parse as a LocalDateTime because the input lacks information about offset-from-UTC or time zone. If this value was meant for UTC, apply an offset to get an OffsetDateTime.

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

If meant for some time zone, transform into a ZonedDateTime.

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

About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old date-time classes such as java.util.Date, .Calendar, & java.text.SimpleDateFormat.

The Joda-Time project, now in maintenance mode, advises migration to java.time.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations.

Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport and further adapted to Android in ThreeTenABP (see How to use…).

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top