开发者

Problem while fetching milliseconds from Date

I have a date in string format as 25 November 2010 and I am trying to fetch the milliseconds of that date, for that I have written the below code:

strDateSelcted = "25 November 2010" // Actually I am receiving date in this format
SimpleDateFormat curFormater = new SimpleDateFormat("dd MMM yyyy"); 
 try {
    Date dateObj = curFormater.parse(strDateSelcted);

        insertEventtoCalendar(dateObj.getTime());   // Actually insert an event onto the native calendar

  } catch (ParseException e) {
    // TODO Auto-generated catch block
        e.printStackTrace();
 } 

But, when I try to run the application,it c开发者_开发技巧reates an event a day before the date inserted, i.e. For 25 November 2010 it inserts event on 24 November 2010 and For 27 November 2010 it inserts event on 26 November 2010, and same.

Where am I making a mistake?


To set the timezone used by the date formatter: call the setTimeZone method e.g.

curFormater.setTimeZone(TimeZone.getTimeZone("UTC"));


For one, your date pattern is wrong, use dd MMMM yyyy. MMM parses & returns Nov (not November).

Also, since there is no millisecond provided in your date string, the millisecond will be set to 0.

Seeing that Jon Skeet updated me with the question, it might be timezone issue (as he mentioned). Sorry for the misunderstanding.

Test code:

/**
 * 
 */

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @author The Elite Gentleman
 *
 */
public class Test {

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        try {
            String date = "25 November 2010";
            SimpleDateFormat sdf = new SimpleDateFormat("dd MMMM yyyy");
            Date d = sdf.parse(date);
            System.out.println(d.getTime());
        } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

Value: 1290636000000


java.time

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*.

Note that a Date-Time without a timezone represents a local Date-Time which may be different for a different timezone e.g. today, it is 31st May 2021 in my timezone, Europe/London whereas 1st June 2021 in Australia/Sydney. So, in order to represent a moment (i.e. an instantaneous point on the timeline in UTC), Java provides a class called Instant which you can convert to other Date-Time types e.g.

import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;

public class Main {
    public static void main(String[] args) {
        Instant now = Instant.now();

        LocalDate todayUK = now.atZone(ZoneId.of("Europe/London")).toLocalDate();
        LocalDate todaySydney = now.atZone(ZoneId.of("Australia/Sydney")).toLocalDate();
        System.out.println(todayUK);
        System.out.println(todaySydney);

        LocalDateTime nowUK = now.atZone(ZoneId.of("Europe/London")).toLocalDateTime();
        LocalDateTime nowSydney = now.atZone(ZoneId.of("Australia/Sydney")).toLocalDateTime();
        System.out.println(nowUK);
        System.out.println(nowSydney);
    }
}

Output:

2021-05-31
2021-06-01
2021-05-31T16:22:40.418214
2021-06-01T01:22:40.418214

So, you need to choose a timezone. Most digital operations are based on the UTC (timezone offset, +00:00 hours).

import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("d MMMM u", Locale.ENGLISH);
        LocalDate date = LocalDate.parse("25 November 2010", dtf);
        ZonedDateTime zdt = date.atStartOfDay(ZoneOffset.UTC);
        Instant instant = zdt.toInstant();
        System.out.println(instant);

        long millis = instant.toEpochMilli();
        System.out.println("Milliseconds since January 1, 1970, 00:00:00 GMT: " + millis);
    }
}

Output:

2010-11-25T00:00:00Z
Milliseconds since January 1, 1970, 00:00:00 GMT: 1290643200000

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

Now, pass millis to your insertEventtoCalendar:

insertEventtoCalendar(millis);

Note: For any reason you need an object of java.util.Date, you can get it from this Instant as

Date date = Date.from(instant);

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

What went wrong with your code?

You tried parsing the date string without setting a timezone and therefore, SimpleDateFormat used your JVM's timezone to parse the date string, giving you a moment/instant corresponding to the start-of-the-day on 25 November 2010 in your timezone. To fix the problem, set the desired Timezone (e.g. UTC) to the SimpleDateFormat instance before parsing i.e.

SimpleDateFormat curFormater = new SimpleDateFormat("dd MMMM yyyy", Locale.ENGLISH);
curFormater.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));

Two more important notes:

  1. Use MMMM instead of MMM for the full monthname.
  2. Never use SimpleDateFormat or DateTimeFormatter without a Locale.

* 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.


It's almost certainly a time zone issue. Check which time zone your SimpleDateFormat is using, and the one your phone is using to display the event.

For diagnostic purposes I suggest you log the result of dateObj.getTime() and you can check exactly what that means on a desktop machine.


Use Locale.getDefault() when Your using SimpleDateFormat.I hope it may solve your problem.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜