I have the following Long variable holding epoch value in seconds, which I'm trying to convert into a Date.
val seconds = 1341855763000
val date = Date(TimeUnit.SECONDS.toMillis(seconds))
The output is way off than I expected. Where did I go wrong?
Actual: Wed Sep 19 05:26:40 GMT+05:30 44491
Expected: Monday July 9 11:12:43 GMT+05:30 2012
The output is way off than I expected. Where did I go wrong?
Actual: Wed Sep 19 05:26:40 GMT+05:30 44491
Expected: Monday July 9 11:12:43 GMT+05:30 2012
The value is already in milliseconds and by using TimeUnit.SECONDS.toMillis(seconds) you are wrongly multiplying it by 1000.
By using the modern date-time API:
import java.time.Instant;
public class Main {
public static void main(String[] args) {
Instant instant = Instant.ofEpochMilli(1341855763000L);
System.out.println(instant);
}
}
Output:
2012-07-09T17:42:43Z
By using legacy java.util.Date:
import java.util.Date;
public class Main {
public static void main(String[] args) {
System.out.println(new Date(1341855763000L));
}
}
Output:
Mon Jul 09 18:42:43 BST 2012
I recommend you switch from the outdated and error-prone java.util date-time API and SimpleDateFormat to the modern java.time date-time API and the corresponding formatting API (package, java.time.format). Learn more about the modern date-time API from Trail: Date Time.
The value you have is not in seconds but in milliseconds. Remove the "seconds to millis" conversion.
val milliSeconds = 1341855763000
val date = Date(milliSeconds)
Your value : 1341855763000 is not in seconds, it is in milliseconds.
The current timestamp is :
new Date().getTime() =>
1598612990351
Same number of digits than :
1341855763000
If you multiply 1341855763000 by 1000 (as you say), it gives the year :
44491 after JC :D
Have a good day
I think your time is actually in milliseconds. If I convert 1341855763000 using this website it gives me your expected time and this as well:
fun main() {
val millis = 1341855763000
val date = Date(millis)
println(date)
}
Alternatively, you can also use seconds:
fun main() {
val seconds = 1341855763L
val date = Date(TimeUnit.SECONDS.toMillis(seconds))
println(date)
}
Just divide by 1000.
Related
I'm writing some integration of legacy code that expects date/time as a GregorianCalendar.
So, I'm creating the GregorianCalendar using from(ZonedDateTime) method.
However, the result is showing some inconsistent behaviour when the GregorianCalendar is created from the ZonedDateTime versus when the GregorianCalendar is created, let's say, from a string parsing or even from epoch millis. For example, when setting the Calendar day_of_week. To demonstrate this (https://onecompiler.com/java/3yssz4q86):
import java.util.*;
import java.time.*;
public class Main {
public static void main(String[] args) {
final GregorianCalendar calendarPure = new GregorianCalendar(TimeZone.getTimeZone("America/Los_Angeles"));
printInfo(calendarPure);
ZoneId zone = ZoneId.of("America/Los_Angeles");
final ZonedDateTime zdtNow = ZonedDateTime.now(zone);
final GregorianCalendar calendarFromZdt = GregorianCalendar.from(zdtNow);
printInfo(calendarFromZdt);
final GregorianCalendar calendarFromZdtEpoch = new GregorianCalendar();
calendarFromZdtEpoch.setTimeInMillis(zdtNow.toInstant().toEpochMilli());
printInfo(calendarFromZdtEpoch);
}
private static void printInfo(GregorianCalendar cal) {
System.out.printf("Now: %tc%n", cal);
System.out.printf("Last Sunday: %tc%n", getLastSunday(cal));
System.out.printf("Week of Year: %d%n", cal.get(Calendar.WEEK_OF_YEAR));
System.out.printf("Time in Millis: %d%n", cal.getTimeInMillis());
System.out.printf("toString(): %s%n", cal);
System.out.println();
}
public static GregorianCalendar getLastSunday(GregorianCalendar referenceDate) {
final GregorianCalendar lastSundayMidNight = (GregorianCalendar)referenceDate.clone();
lastSundayMidNight.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
return lastSundayMidNight;
}
}
The output is:
Now: Wed Dec 28 16:45:36 PST 2022
Last Sunday: Sun Dec 25 16:45:36 PST 2022
Week of Year: 53
Time in Millis: 1672274736631
toString(): java.util.GregorianCalendar[time=1672274736631,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="America/Los_Angeles",offset=-28800000,dstSavings=3600000,useDaylight=true,transitions=185,lastRule=java.util.SimpleTimeZone[id=America/Los_Angeles,offset=-28800000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=3,startMonth=2,startDay=8,startDayOfWeek=1,startTime=7200000,startTimeMode=0,endMode=3,endMonth=10,endDay=1,endDayOfWeek=1,endTime=7200000,endTimeMode=0]],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2022,MONTH=11,WEEK_OF_YEAR=53,WEEK_OF_MONTH=5,DAY_OF_MONTH=28,DAY_OF_YEAR=362,DAY_OF_WEEK=4,DAY_OF_WEEK_IN_MONTH=4,AM_PM=1,HOUR=4,HOUR_OF_DAY=16,MINUTE=45,SECOND=36,MILLISECOND=631,ZONE_OFFSET=-28800000,DST_OFFSET=0]
Now: Wed Dec 28 16:45:36 PST 2022
Last Sunday: Sun Jan 01 16:45:36 PST 2023
Week of Year: 52
Time in Millis: 1672274736668
toString(): java.util.GregorianCalendar[time=1672274736668,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="America/Los_Angeles",offset=-28800000,dstSavings=3600000,useDaylight=true,transitions=185,lastRule=java.util.SimpleTimeZone[id=America/Los_Angeles,offset=-28800000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=3,startMonth=2,startDay=8,startDayOfWeek=1,startTime=7200000,startTimeMode=0,endMode=3,endMonth=10,endDay=1,endDayOfWeek=1,endTime=7200000,endTimeMode=0]],firstDayOfWeek=2,minimalDaysInFirstWeek=4,ERA=1,YEAR=2022,MONTH=11,WEEK_OF_YEAR=52,WEEK_OF_MONTH=5,DAY_OF_MONTH=28,DAY_OF_YEAR=362,DAY_OF_WEEK=4,DAY_OF_WEEK_IN_MONTH=4,AM_PM=1,HOUR=4,HOUR_OF_DAY=16,MINUTE=45,SECOND=36,MILLISECOND=668,ZONE_OFFSET=-28800000,DST_OFFSET=0]
Now: Thu Dec 29 00:45:36 UTC 2022
Last Sunday: Sun Dec 25 00:45:36 UTC 2022
Week of Year: 53
Time in Millis: 1672274736668
toString(): java.util.GregorianCalendar[time=1672274736668,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Etc/UTC",offset=0,dstSavings=0,useDaylight=false,transitions=0,lastRule=null],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2022,MONTH=11,WEEK_OF_YEAR=53,WEEK_OF_MONTH=5,DAY_OF_MONTH=29,DAY_OF_YEAR=363,DAY_OF_WEEK=5,DAY_OF_WEEK_IN_MONTH=5,AM_PM=0,HOUR=0,HOUR_OF_DAY=0,MINUTE=45,SECOND=36,MILLISECOND=668,ZONE_OFFSET=0,DST_OFFSET=0]
I noticed that, from GregorianCalendar.toString() that prints the internal fields a different in firstDayOfWeek and minimalDaysInFirstWeek. That could be the cause for the divergence in the after results. I wonder where the GregorianCalendar is getting these values from. Maybe there is a way to set something on ZonedDateTime object that will ensure the results will be the same? Couldn't find anything on javadocs.
Note: Please, don't tell me not to use GregorianCalendar. I know, I know. I'm just writing an integration for two pieces of code that I'm not allowed to modify, one uses GregorianCalendar (sigh), the other uses ZonedDateTime.
I am having an issue while parsing day and time to get the total hours and minutes in java.
If I calculate total hours starting from 'Mon 22:00' to 'Tue 22:00' then I am getting correct total hours 24. But If I calculate total hours starting from 'Wed 22:00' to current day and time like 'Thu 12:45' then I am getting 'Hours : -153 Min : -15'.
This is the case only for Wednesday and Thursday. For rest of the days it is working fine.
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.concurrent.TimeUnit;
public class Test {
private static DateFormat dateFormat = new SimpleDateFormat("EEE HH:mm");
private static DateFormat dayFormat = new SimpleDateFormat("E");
private static Calendar calendar = Calendar.getInstance();
public static void main(String[] args) {
try {
Date date1 = dateFormat.parse("Wed 22:00");
Date date2 = dateFormat.parse(dayFormat.format(calendar.getTime()) + " " + calendar.getTime().getHours() + ":"
+ calendar.getTime().getMinutes());
long hours2 = getDurationInHours(date1, date2);
long min = getDurationInMin(date1, date2);
System.out.println("Hours : " + hours2 + " Min : " + min);
} catch (Exception e) {
e.printStackTrace();
}
}
public static long getDurationInHours(Date returnTime, Date leaveTime) {
long durationInMillis = leaveTime.getTime() - returnTime.getTime();
long hours = TimeUnit.MILLISECONDS.toHours(durationInMillis);
return hours;
}
public static long getDurationInMin(Date returnTime, Date leaveTime) {
long durationInMillis = leaveTime.getTime() - returnTime.getTime();
long min = TimeUnit.MILLISECONDS.toMinutes(durationInMillis) % 60;
return min;
}
}
That's because when you define your date as Wed 22:00 it's not the Wednesday the current week. It is actually 7th of January 1970 ;)
As you probably know the dates in java work as long number since 01.01.1970. So when you say Wednesday and not an actual date it gets the first Wednesday after 1970 which is the 7th. When you say Mon 22:00 it works properly because it uses 5th of January 1970 and the difference is 2 days.
When you use "Thu 22:00" in the same logic it uses 1st of January 1970 (which is a Thursday) and that's why you get negative numbers. Because it's actually 6 days ahead
java.time
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEE H:mm", Locale.ENGLISH);
ZonedDateTime now = ZonedDateTime.now(ZoneId.of("America/Dominica"));
TemporalAccessor fromTa = formatter.parse("Wed 22:00");
ZonedDateTime from = now
.with(TemporalAdjusters.previous(DayOfWeek.from(fromTa)))
.with(LocalTime.from(fromTa));
Duration dur = Duration.between(from, now);
System.out.println(dur);
Running this code just now gave the following output:
PT11H41M25.284611S
This means a duration of 11 hours 41 minutes 25.284611 seconds. If you need to use this duration further in your program, you will probably want to keep the Duration object. For printing to the user it’s not so nice, so do that this way:
long hours = dur.toHours();
int min = dur.toMinutesPart();
System.out.println("" + hours + " hours " + min + " min");
11 hours 41 min
Java doesn’t have a concept of “Wednesday at 22:00”. So we need to pick a specific Wednesday and a specific Thursday. SimpleDateFormat was trying to be helpful to you and picked for you, but didn’t pick the Wednesday and the Thursday you had expected, so didn’t do you any favour. java.time, the modern Java date and time API, forces us to pick ourselves. I much prefer this. It makes it much clearer exactly what happens in the code, which in turn will also make it easier to spot and fix any errors.
My use of TemporalAdjusters.previous ensures that I get last Wednesday (not next Wednesday). And my use of ZonedDateTime ensures that the hours and minutes are correct. Even across transitions to and from summer time (daylight saving time) and other such time transitions. You should of course fill in your own time zone if it didn’t happen to be America/Dominica.
Link: Oracle tutorial: Date Time explaining how to use java.time.
The date-time API of java.util 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.
You can do it in an intuitive way with java.time.Duration which is modelled on ISO-8601 standards and was introduced with Java-8 as part of JSR-310 implementation. With Java-9 some more convenience methods were introduced.
Note that a weekday and time e.g. Mon 22:00 is not sufficient to create a date-time object directly. A weekday e.g. Monday comes in every week and therefore we will have to create a date-time object defaulting to a particular date e.g. today. From this date as a reference, you can find the first occurrence (LocalDate) of the given weekday (e.g. Monday) and from that object, you can obtain a date-time object with the given time.
Duration#between gives you the Duration object between the two date-time objects. Using the Duration object, you can create a string formatted as per your requirement, by getting days, hours, minutes, seconds from it.
Demo:
import java.time.DayOfWeek;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAccessor;
import java.time.temporal.TemporalAdjusters;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
// Test
displayDuration(getDuration("Mon 22:00", "Tue 22:00"));
displayDuration(getDuration("Wed 22:00", "Thu 12:45"));
}
static Duration getDuration(String strStartDayTime, String strEndDayTime) {
LocalDate today = LocalDate.now();
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("EEE HH:mm", Locale.ENGLISH);
TemporalAccessor taStart = dtf.parse(strStartDayTime);
TemporalAccessor taEnd = dtf.parse(strEndDayTime);
LocalDateTime ldtStartDateTime = today.with(TemporalAdjusters.nextOrSame(DayOfWeek.from(taStart)))
.atTime(LocalTime.from(taStart));
LocalDateTime ldtEndDateTime = today.with(TemporalAdjusters.nextOrSame(DayOfWeek.from(taEnd)))
.atTime(LocalTime.from(taEnd));
return Duration.between(ldtStartDateTime, ldtEndDateTime);
}
static String formatDurationJava8(Duration duration) {
return String.format("Days: %d, Hours: %02d, Minutes: %02d, Seconds: %02d", duration.toDays(),
duration.toHours() % 24, duration.toMinutes() % 60, duration.toSeconds() % 60);
}
static String formatDurationJava9(Duration duration) {
return String.format("Days: %d, Hours: %02d, Minutes: %02d, Seconds: %02d", duration.toDaysPart(),
duration.toHoursPart(), duration.toMinutesPart(), duration.toSecondsPart());
}
static void displayDuration(Duration duration) {
// Default format
System.out.println(duration);
// Custom format
System.out.println(formatDurationJava8(duration));
System.out.println(formatDurationJava9(duration));
}
}
Output:
PT24H
Days: 1, Hours: 00, Minutes: 00, Seconds: 00
Days: 1, Hours: 00, Minutes: 00, Seconds: 00
PT14H45M
Days: 0, Hours: 14, Minutes: 45, Seconds: 00
Days: 0, Hours: 14, Minutes: 45, Seconds: 00
Learn about 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.
This question already has answers here:
String to Date conversion returning wrong value
(5 answers)
Closed 5 years ago.
I am trying to find the difference between two dates and I did the following:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class test {
public static void main(String[] args) {
Date date = new Date();
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-DD");
String accessioned = "2017-04-27";
System.out.println(date);
try {
date = format.parse(accessioned);
} catch (ParseException e) {
e.printStackTrace();
}
System.out.println(date);
Date now = new Date();
long diff = now.getTime() - date.getTime();
System.out.println(diff);
if ((diff / (1000 * 60 * 60 * 24)) >= 30) {
System.out.println("haha");
}
}
}
This is the output I get:
Fri Jul 21 14:23:59 CEST 2017
Fri Jan 27 00:00:00 CET 2017
15168239705
haha
The Problem is if I change the the String accessioned for e.g to "2017-04-28" the date changes accordingly, same thing for year but whatever value I put for month, It always outputs January. For e.g in my code it should be April but the output says Jan.
What am I doing wrong?
Change D to d (SimpleDateFormat Doc):
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
D is for day in year (1-365)
d is for day in month (1-31)
Also you can now use LocalDate from Java8 more convenient to use DateTimeFormatter Doc / LocalDate Doc
You apparently want to check if the difference of days is >=30 between your date and now or not, so I'll propose another solution with LocalDate :
LocalDate localDate = LocalDate.parse("2017-04-27", DateTimeFormatter.ofPattern("yyyy-MM-dd"));
long daysDiff = localDate.until(LocalDate.now(), ChronoUnit.DAYS);
System.out.println(daysDiff);
if (daysDiff >= 30){
System.out.println("haha");
}
EDIT : You need to use LocalDateTime instead of LocalDate to be able to use hour/minute/sec also
LocalDateTime localDateTime = LocalDateTime.parse("2017-04-21T11:51:36Z", DateTimeFormatter.ISO_DATE_TIME);
The problem is your date format: new SimpleDateFormat("yyyy-MM-DD")
As listed here, M is already a two-digit format - and D stands for "Day in year", not "Day in month", which is d.
Your format should look like this:
SimpleDateFormat("y-M-d")
...which gives me:
Fri Jul 21 14:44:03 CEST 2017
Thu Apr 27 00:00:00 CEST 2017
7397043764
haha
I am using the code below on Mac OSX 10.10.2 and it's behaving strangely.
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
public class StringToDate {
public static void main(String[] args) throws Exception {
String dateInString = "23/Oct/2015";
DateFormat formatter = new SimpleDateFormat("dd/MMM/YYYY");
Date date = formatter.parse(dateInString);
System.out.println(date);
}
}
Output on Mac: Sun Dec 28 00:00:00 CST 2014
Output on Windows: Fri Oct 23 00:00:00 CDT 2015
Why is the Mac output wrong?
Y is for the week year. Use y for the year.
DateFormat formatter = new SimpleDateFormat("dd/MMM/yyyy");
Also, make sure the DateFormat's locale is the right one.
EDIT:
A Date has millisecond precision, so if you want nanosecond precision, you shouldn't use Date and SimpleDateFormat.
S is for milliseconds. Since you tell SimpleDateFormat that the last part of the string is milliseconds, it parses it as that: 545000000 milliseconds (i.e. a bit more than 6 days, which explains the difference between the input and the output).
To get an accurate result, to the millisecond, remove the last 6 characters of the string, and use the pattern "dd-MMM-yyyy-HH.mm.ss.SSS".
Background:
In my database table, I have two timestamps
timeStamp1 = 2011-08-23 14:57:26.662
timeStamp2 = 2011-08-23 14:57:26.9
When I do an "ORDER BY TIMESTAMP ASC", timeStamp2 is considered as the greater timestamp(which is correct).
Requirement: I need to get the difference of these timestamps (timeStamp2 - timeStamp1)
My implementation:
public static String timeDifference(String now, String prev) {
try {
final Date currentParsed = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").parse(now);
final Date previousParsed = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").parse(prev);
long difference = currentParsed.getTime() - previousParsed.getTime();
return "" + difference;
} catch (ParseException e) {
return "Unknown";
}
}
The answer should have been 238ms, but the value that is returned is -653ms.
I'm not sure what I'm doing wrong. Any suggestions?
The format you are parsing and the format uses doesn't match. You expect a three digit field and are only providing one digits. It takes 9 and assumes you mean 009 when what you want is 900. Date formats are complicated and when you prove dates in a different format it may parse them differently to you.
The documentation says S means the number of milli-seconds and the number in that field is 9, so it is behaving correctly.
EDIT: This example may help
final SimpleDateFormat ss_SSS = new SimpleDateFormat("ss.SSS");
ss_SSS.setTimeZone(TimeZone.getTimeZone("GMT"));
for (String text : "0.9, 0.456, 0.123456".split(", ")) {
System.out.println(text + " parsed as \"ss.SSS\" is "
+ ss_SSS.parse(text).getTime() + " millis");
}
prints
0.9 parsed as "ss.SSS" is 9 millis
0.456 parsed as "ss.SSS" is 456 millis
0.123456 parsed as "ss.SSS" is 123456 millis
I'm not entirely sure, but the JavaDoc states this:
For parsing, the number of pattern letters is ignored unless it's needed to separate two adjacent fields.
This indicates that the milliseconds from 2011-08-23 14:57:26.9 would be parsed as 9 instead of 900. Adding the trailing zeros might work: 2011-08-23 14:57:26.900.
I'd suggest using Joda-Time. It handles these situations properly. In the following example, the milliseconds are correctly parsed as 200ms.
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
public class ParseMillis {
public static void main(String[] args) {
String s = "00:00:01.2";
DateTimeFormatter format = DateTimeFormat.forPattern("HH:mm:ss.S");
DateTime dateTime = format.parseDateTime(s);
System.out.println(dateTime.getMillisOfSecond());
}
}
I had the same problem with too accurate time from my logfiles with 6 digit milliseconds. Parsing Time gave up to 16 minutes difference! WTF?
16-JAN-12 04.00.00.999999 PM GMT --> 16 Jan 2012 04:16:39 GMT
Changing the number of digits reduced the erroneous difference and thanks to this thread I could identify the problem:
16-JAN-12 04.00.00.99999 PM GMT --> 16 Jan 2012 04:01:39 GMT
16-JAN-12 04.00.00.9999 PM GMT --> 16 Jan 2012 04:00:09 GMT
16-JAN-12 04.00.00.999 PM GMT --> 16 Jan 2012 04:00:00 GMT
As SimpleDateFormat internally handles only 3 digits I removed the unnecessary with a small regex (ignoring round-off errors, working for 1 up to n digits):
str = str.replaceAll("(\\.[0-9]{3})[0-9]*( [AP]M)", "$1$2");
Thanks to #Peter Lawrey for your answer, prevented me going insane :-)