Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generating UTC Time in java

I want to get the UTC time for 01/01/2100 in Java to '2100-01-01 00:00:00'. I am getting "2100-01-01 00:08:00". Any idea, how to correct this.

public Date getFinalTime() {
    Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));

    DateFormat df = new SimpleDateFormat("dd/MM/yyyy");
    Date finalTime = null;

    try
    {
        finalTime = df.parse("01/01/2100");            
    } catch (ParseException e)
    {
        e.printStackTrace();
    }

    calendar.setTime(finalTime);
    return calendar.getTime();
}
like image 855
Boolean Avatar asked Jul 29 '10 19:07

Boolean


3 Answers

You need to specify the time zone for the SimpleDateFormat as well - currently that's parsing midnight local time which is ending up as 8am UTC.

TimeZone utc = TimeZone.getTimeZone("UTC");
Calendar calendar = Calendar.getInstance(utc);

DateFormat df = new SimpleDateFormat("dd/MM/yyyy");
df.setTimeZone(utc);
Date finalTime = null;

try
{
    finalTime = df.parse("01/01/2100");            
} catch (ParseException e)
{
    e.printStackTrace();
}

calendar.setTime(finalTime);

As ever though, I would personally recommend using Joda Time which is far more capable in general. I'd be happy to translate your example into Joda Time if you want.

Additionally, I see you're returning calendar.getTime() - that's just the same as returning finalTime as soon as you've computed it.

Finally, just catching a ParseException and carrying on as if it didn't happen is a very bad idea. I'm hoping this is just sample code and it doesn't reflect your real method. Likewise I'm assuming that really you'll be parsing some other text - if you're not, then as Eyal said, you should just call methods on Calendar directly. (Or, again, use Joda Time.)

like image 179
Jon Skeet Avatar answered Nov 19 '22 04:11

Jon Skeet


You need to set the time zone of the SimpleDateFormat object as well, otherwise it assumes the default time zone.

Anyway, it seems like using only a Calendar is enough in your case. Use its setters to set the right values for all fields (year, month, day, hour, etc), and then retrieve the time.

like image 3
Eyal Schneider Avatar answered Nov 19 '22 06:11

Eyal Schneider


The java.util Date-Time API and their formatting API, SimpleDateFormat are outdated and error-prone. It is recommended to stop using them completely and switch to the modern Date-Time API*.

Also, quoted below is a notice at the Home Page of Joda-Time:

Note that from Java SE 8 onwards, users are asked to migrate to java.time (JSR-310) - a core part of the JDK which replaces this project.

Solution using java.time, the modern API:

import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        String strDate = "01/01/2100";
        DateTimeFormatter dtfInput = DateTimeFormatter.ofPattern("d/M/u", Locale.ENGLISH);
        
        ZonedDateTime zdt = LocalDate.parse(strDate, dtfInput)
                                .atStartOfDay(ZoneId.of("Etc/UTC"));

        // Default format
        System.out.println(zdt);

        // Getting and displaying LocalDateTime
        LocalDateTime ldt = zdt.toLocalDateTime();
        System.out.println(ldt);

        // A custom format
        DateTimeFormatter dtfOutput = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss", Locale.ENGLISH);
        // Alternatively dtfOutput.format(ldt);
        String formatted = dtfOutput.format(zdt);
        System.out.println(formatted);
        
        // Converting to some other types
        OffsetDateTime odt = zdt.toOffsetDateTime();
        Instant instant = zdt.toInstant();
        System.out.println(odt);
        System.out.println(instant);
    }
}

Output:

2100-01-01T00:00Z[Etc/UTC]
2100-01-01T00:00
2100-01-01 00:00:00
2100-01-01T00:00Z
2100-01-01T00:00:00Z

ONLINE DEMO

The Z in the output is the timezone designator for zero-timezone offset. It stands for Zulu and specifies the Etc/UTC timezone (which has the timezone offset of +00:00 hours).

Note: The Date-Time without timezone name or timezone offset should be represented by LocalDateTime (which is used for events that are normally not represented with timezone information). In this sense, LocalDateTime is useless in this case and you should use ZonedDateTime itself or Instant or OffsetDateTime. I recommend you also check this answer and this answer if you are dealing with JDBC.

Learn more about java.time, the modern Date-Time API* from Trail: Date Time.


* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.

like image 3
Arvind Kumar Avinash Avatar answered Nov 19 '22 05:11

Arvind Kumar Avinash