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:
- Use
MMMM
instead ofMMM
for the full monthname. - 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.
精彩评论