java.util.Date get milliseconds - java

I have done the following:
String standardRange = "00:01:01";
SimpleDateFormat rangeFormatter = new SimpleDateFormat("hh:mm:ss");
Date range = rangeFormatter.parse(standardRange);
Now:
range.getTime();
.. I get the output of -3539000 and not 61,000
I'm not sure what I'm doing wrong; when debugging, cdate exists, the attribute contains a fraction, which contains the value 61,000, which is what I want.

The reason you're seeing this is that the date you're creating is actually in the past of the date epoch, not 1m1s after it:
String standartRange = "00:01:01";
SimpleDateFormat rangeFormatter = new SimpleDateFormat("hh:mm:ss");
Date range = rangeFormatter.parse(standartRange);
System.out.println(new Date(0L));
System.out.println(new Date(0L).getTime());
System.out.println(range);
System.out.println(range.getTime());
and its output;
Thu Jan 01 01:00:00 GMT 1970
0
Thu Jan 01 00:01:01 GMT 1970
-3539000
The epoch date is incorrect here - it should be 00:00:00, but due to a historical bug where BST/GMT changed dates and timezone cant keep track. It seems that Sun/Oracle consider this a historical "inaccuracy".
Check out the bug report - its describes the problem more fully.
From your language (German) this may not be directly due to this BST issue, but its almost certainly related.

Java Date is not designed to calculate the duration of a given time period.
The getTime() call returns the numbers of milliseconds since January 1, 1970, 00:00:00 GMT. In your case you are actually ending up with a date that comes before that epoch (thus the negative number). When I run your code I get 21661000. (See the answer from Sean Landsman as I believe he has hit on why you get the negative results...hint: my number is exactly 6 hours off of GMT or 21600000ms)
Joda-Time is a library that is well suited to solving your underlying problem.
PeriodFormatter formatter = new PeriodFormatterBuilder()
.appendHours()
.appendSeparator(":")
.appendMinutes()
.appendSeparator(":")
.appendSeconds()
.toFormatter();
Period period = formatter.parsePeriod("00:01:01");
assert period.toStandardDuration().getMillis() == 61000

According to the JavaDoc, getTime():
Returns the number of milliseconds since January 1, 1970, 00:00:00 GMT represented by this Date object.
You want the number of milliseconds in one minute and one second.
(60*minutes+seconds)*1000
It really doesn't need to come from a Date object.
If you need to compute the time in milliseconds for some interval, maybe use the joda time library, or get the day, hour, minute, second and millisecond components out of your date object and compute the value by hand.

To get what you want, you should compare between the time you want and origin of the time. using the below code:
String standardRange = "00:01:01";
SimpleDateFormat rangeFormatter = new SimpleDateFormat("HH:mm:ss");
Date range = rangeFormatter.parse(standardRange);
Date range2 = rangeFormatter.parse("00:00:00");
System.out.println(range.getTime() - range2.getTime());

hh:mm:ss stands for 12-hour time, which always stands for "time point", not "time interval". So surely, time zone will effect the value. However, in GMT +0 the value equals to which represents "time interval".
All you just need is:
rangeFormatter.setTimeZone(TimeZone.getTimeZone("GMT"));
Try it!

Try:
Date range1 = rangeFormatter.parse("00:01:01");
Date range2 = rangeFormatter.parse("00:00:00");
System.out.println(range1.getTime() - range2.getTime());

Related

error output converting date format from YYYYMMDD to dd-mm-yyyy

I have a problem on the java conversion of the dates.
I have input a String, YYYYMMDD, that converts to long and by executing the code the output is wrong
try {
//Current date to dd-mm-yyyy
Date currentDate = new Date(20161205); //or
DateFormat df = new SimpleDateFormat("dd-mm-yyyy");
String strCurrentDate = df.format(currentDate);
System.out.println("Date is " + strCurrentDate);
} catch (Exception e) {
System.out.println("Exception :" + e);
}
The output is: 01-49-1970
why?? How can I solve the problem
Solution:
Date currentDate = new Date(116,11,05);
Explanation:
You put single number as an argument of constructor of Date. If you take a look at list of available constructors of this class in Java API documentation here, you'll notice that the one taking long as argument will be chosen. As documentation states:
Date​(long date) - Allocates a Date object and initializes it to represent the specified number of milliseconds since the standard base time known as "the epoch", namely January 1, 1970, 00:00:00 GMT.
Instead of that, if you really need to use java.util.date package (java.time is considered as the right choice nowadays), consider using another constructor: Date​(int year, int month, int date). In that case, you should pass the following numbers as parameters:
Date currentDate = new Date(116,11,05);
This is because:
year - the year minus 1900.
month - the month between 0-11.
date - the day of the month between 1-31.
By the way, consider using java.time package instead of java.util as java.util.Date is now deprecated.
you are doing it in the wrong way see
if you want to change date from this formate yyyyMMdd to this formateyyyy-MM-dd
you have to to change your code a little bit
try {
//Current date to dd-mm-yyyy
DateFormat fromFormate = new SimpleDateFormat("yyyyMMdd");
DateFormat toFormate = new SimpleDateFormat("yyyy-MM-dd");
String dateToFormate = "20161205"; //or
Date d=fromFormate.parse(dateToFormate);
System.out.println("Date is " + toFormat.formate(d));
} catch (Exception e) {
System.out.println("Exception :" + e);
}
tl;dr
LocalDate.parse(
"20161205",
DateTimeFormatter.BASIC_ISO_DATE
).format(
DateTimeFormatter.ofPattern("dd-MM-uuuu")
)
05-12-2016
Why 01-49-1970?
I cannot reproduce your exact output so can explain most of it, not all. Probably you’ve confused a couple of your test examples and didn’t get 01-49-1970 from new Date(20161205). On my computer I got Date is 01-36-1970. It’s bad enough.
As others have pointed out, new Date(20161205) gives you a point in time a little more than 20 000 seconds after the epoch of January 1, 1970 00:00 UTC. In UTC the time is then 5:36:01.205 (AM) on January 1. The time in your time zone probably differs. There are time zones where the date is still December 31, 1969.
But this doesn’t seem to explain how you seem to get an output in the 49th month of 1970, or I in the 36th month. This is because you used lowercase mm in your format pattern string. mm is for minute of hour. Uppercase MM is for month. So the 36 I got matches the minutes in the 5:36:01. There are time zones where the minutes are not the same; but I couldn’t find a time zone where the minute of hour is 49 at this time, so your exact reported output I cannot explain.
How can I solve the problem?
As others have said too, use java.time, the modern Java date and time API. It is so much nicer to work with.
LocalDate currentDate = LocalDate.of(2016, Month.DECEMBER, 5);
Or from a string:
LocalDate currentDate
= LocalDate.parse("20161205", DateTimeFormatter.BASIC_ISO_DATE);
Format to your desired output:
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("dd-MM-uuuu");
String strCurrentDate = currentDate.format(dtf);
System.out.println("Date is " + strCurrentDate);
This prints
Date is 05-12-2016
As a bonus java.time will let you know through an exception if you happen to use mm instead of MM in the format pattern string above.
Link: Oracle Tutorial: Date Time explaining how to use java.time.
Like #oceano22 said, there are newer/better date/time packages available. That said, the reason this is happening is because when you called new Date(20161205) the parameter that date constructor takes is NOT yyyyMMdd. According to the javadoc... "Allocates a Date object and initializes it to represent the specified number of milliseconds since the standard base time known as "the epoch", namely January 1, 1970, 00:00:00 GMT."
So really you've created a date just 20 million milliseconds after the Unix epoch (Jan 1, 1970).
I've you're trying to get Dec 5, 2016 into a Date use df.parse("05-12-2016") with the SimpleDateFormat df you have defined.
You also likely want capital M's for month in your date format e.g. "dd-MM-yyyy" because lowercase m's are for minutes.

Java time problems

I have a problem of inconsistency with time objects
Time time1 = new Time(72000000); //21:00
Time time2 = new Time(new Date().getTime()); //before 21 pm
time2.before(time1);
The last line returns always false, why?
Time:
A thin wrapper around the java.util.Date class that allows the JDBC API to identify this as an SQL TIME value. The Time class adds formatting and parsing operations to support the JDBC escape syntax for time values.
The date components should be set to the "zero epoch" value of January 1, 1970 and should not be accessed.
http://docs.oracle.com/javase/7/docs/api/java/sql/Time.html
Basically you're comparing 21:00 at the first of january 1970 to your current date at some point in the day. Obviously the former time happens earlier and is 'smaller'.
This is not doing what you think it's supposed to do!
Time time1 = new Time(72000000);
See this:
Time
public Time(long time)
Constructs a Time object using a milliseconds time value.
Parameters:
time - milliseconds since January 1, 1970, 00:00:00 GMT; a negative number is milliseconds before January 1, 1970, 00:00:00 GMT
Now, hopefully you understand...
Since you didn't specify otherwise, I assume that the Time object is java.sql.Time.
This object uses a superclass of java.util.Date so it is actually a full date object. For the purposes of JDBC (SQL) it only concerns itself with the time portion of the date.
This:
Time time1 = new Time(72000000);
...creates an object that represents 1-January-1970 21:00 hours. It will always be before any current time.
Seems that time1 is 14:00 . Run the below code snippet.
Time time1 = new Time(72000000); //21:00
System.out.println(time1); //prints 14:00
System.out.println(new Date());
Time time2 = new Time(new Date().getTime()); //before 21 pm

Java SimpleDateFormat: an hour wrong

I don't need a whole story to clarify my question, so I'll just show the code (which is a mere example). How come there is a difference in my result?
Code
long millis = 2305293L;
System.out.println(
millis + "ms = " +
(millis / 1000) + "s = " +
(millis / 1000 / 60) + "m");
System.out.println(
new SimpleDateFormat("HH:mm:ss").
format(
new Date(millis)
)
);
Output
2305293ms = 2305s = 38m
01:38:25
If you are in London, or Paris, the timezone was GMT+1 on 1 Jan 1970.
For reasons #ARC explains in the comments, the UK used GMT+1 or UTC+1 from 18 Feb 1968 to 31 Oct 1971
is it possible for me to convert a long without any timezones interfering?
Set the TimeZone to be GMT.
long millis = 2305293L;
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss.SSS");
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
System.out.println(sdf.format(new Date(millis)));
prints
00:38:25.293
Try this :
System.out.println(new java.util.Date (0));
you will see it begins at 01:00:00, hence the difference of one hour.
The other answers are correct and were good answers when the question was asked in 2013. Today we should no longer use Date nor SimpleDateFormat, so I would like to show you a couple of modern code snippets instead. The correct way to format your (in this case) 2 305 293 milliseconds depends on what they represent. I am presenting three options for three different situations.
Formatting a number of milliseconds since the epoch
You need to decide in which time zone you want to interpret your point in time. For example:
long millis = 2_305_293L;
DateTimeFormatter formatter = DateTimeFormatter
.ofLocalizedDateTime(FormatStyle.LONG)
.withLocale(Locale.ENGLISH);
ZonedDateTime dateTime = Instant.ofEpochMilli(millis)
.atZone(ZoneId.of("America/Coral_Harbour"));
String formattedTime = dateTime.format(formatter);
System.out.println(formattedTime);
December 31, 1969 at 7:38:25 PM EST
Since at the epoch Coral Harbor was at UTC offset -05:00, we get a time near the end of 1969. If you want the time in UTC (since the epoch is defined in UTC; in other words, if you want 00:38:25), it’s a bit different:
DateTimeFormatter formatter = DateTimeFormatter
.ofLocalizedDateTime(FormatStyle.MEDIUM)
.withLocale(Locale.ENGLISH);
OffsetDateTime dateTime = Instant.ofEpochMilli(millis)
.atOffset(ZoneOffset.UTC);
Jan 1, 1970, 12:38:25 AM
In addition to time zone you may vary the language through the locale and the length of the format through the format style (full, long, medium, short). If you want the time of day without the date, use ofLocalizedTime instead of ofLocalizedDateTime.
Formatting a millisecond of day
Assuming your milliseconds are since 0:00 (“midnight”) in whatever time zone:
LocalTime time = LocalTime.MIN.with(ChronoField.MILLI_OF_DAY, millis);
System.out.println(time);
00:38:25.293
If this format is satisfactory, you don’t need any explicit formatter. If not, you may use a DateTimeFormatter.
Formatting a duration, an amount of time
An amount of time is a completely different thing from a time and is handled as a Duration object. There is no direct support for formatting it, but since Java 9 it’s not so hard (when you know how):
Duration amountOfTime = Duration.ofMillis(millis);
String formattedTime = String.format("%02d:%02d:%02d",amountOfTime.toHours(),
amountOfTime.toMinutesPart(), amountOfTime.toSecondsPart());
System.out.println(formattedTime);
00:38:25
Link
Oracle tutorial: Date Time explaining how to use java.time.

strip time from timestamp

Why cannot I clear the time from a timestamp this way:
one day == 24 * 3600 * 1000 == 86400000 milliseconds.
long ms = new Date().getTime(); //Mon Sep 03 10:06:59 CEST 2012
Date date = new Date(ms - (ms % 86400000));
how come this is Mon Sep 03 02:00:00 CEST 2012 instead of Mon Sep 03 00:00:00 CEST 2012?
Why cannot I clear time from timestamm this way
You're correctly clearing the time part in UTC. The millisecond values in Date are always relative to January 1st 1970 midnight in UTC. However, you're not displaying it in UTC, because of the way Date.toString() works (it always uses the system local time zone). Note that a Date itself has no concept of a time zone. It's just a number of milliseconds since January 1st 1970 midnight UTC.
The concept of "clearing a time from a timestamp" doesn't really make sense without specifying which time zone you're talking about, as the same timestamp will have different times of day (and even dates) in different time zones.
To be honest, I would suggest using Joda Time for any significant date/time work. Then you can create a LocalDate which is obviously meant to represent "just a date" - and the translation from a Date (or Instant) to a LocalDate will make it easy for you to specify whichever time zone you want to use.
I actually want to compare it to another date not taking into account time of day
To compare dates I suggest using JodaTime which supports this functionality with LocalDate
LocalDate date1 = new LocalDate(); // just the date without a time or time zone
LocalDate date2 = ....
if (date1.compareTo(date2) <=> 0)
Note: this will construct timezone-less LocalDates which is appropriate for the default timezone. As long as you are only talking about the timezone where the default timezone for the machine has been set, this is fine. e.g. say you have a timezone of CEST then this is fine for most of Europe.
Using the built in time functions you can do something like
public static int compareDatesInTimeZone(Date d1, Date d2, TimeZone tz) {
long t1 = d1.getTime();
t1 += tz.getOffset(t1);
long t2 = d2.getTime();
t2 += tz.getOffset(t2);
return Double.compare(t1 / 86400000, t2 / 86400000);
}
Try this...
Calendar c = Calendar.getInstance();
DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT);
String strDate = df.format(c.getTime()));
Now this way you can have the another date, and then compare it....as they are now in String format.

Converting Long to Date in Java returns 1970

I have list with long values (for example: 1220227200, 1220832000, 1221436800...) which I downloaded from web service. I must convert it to Dates. Unfortunately this way, for example:
Date d = new Date(1220227200);
returns 1 Jan 1970. Anyone know another way to convert it correctly?
The Date constructor (click the link!) accepts the time as long in milliseconds, not seconds. You need to multiply it by 1000 and make sure that you supply it as long.
Date d = new Date(1220227200L * 1000);
This shows here
Sun Aug 31 20:00:00 GMT-04:00 2008
tl;dr
java.time.Instant // Represent a moment as seen in UTC. Internally, a count of nanoseconds since 1970-01-01T00:00Z.
.ofEpochSecond( 1_220_227_200L ) // Pass a count of whole seconds since the same epoch reference of 1970-01-01T00:00Z.
Know Your Data
People use various precisions in tracking time as a number since an epoch. So when you obtain some numbers to be interpreted as a count since an epoch, you must determine:
What epoch?Many epochs dates have been used in various systems. Commonly used is POSIX/Unix time, where the epoch is the first moment of 1970 in UTC. But you should not assume this epoch.
What precision?Are we talking seconds, milliseconds, microseconds, or nanoseconds since the epoch?
What time zone?Usually a count since epoch is in UTC/GMT time zone, that is, has no time zone offset at all. But sometimes, when involving inexperienced or date-time ignorant programmers, there may be an implied time zone.
In your case, as others noted, you seem to have been given seconds since the Unix epoch. But you are passing those seconds to a constructor that expects milliseconds. So the solution is to multiply by 1,000.
Lessons learned:
Determine, don't assume, the meaning of received data.
Read the doc.
Your Data
Your data seems to be in whole seconds. If we assume an epoch of the beginning of 1970, and if we assume UTC time zone, then 1,220,227,200 is the first moment of the first day of September 2008.
Joda-Time
The java.util.Date and .Calendar classes bundled with Java are notoriously troublesome. Avoid them. Use instead either the Joda-Time library or the new java.time package bundled in Java 8 (and inspired by Joda-Time).
Note that unlike j.u.Date, a DateTime in Joda-Time truly knows its own assigned time zone. So in the example Joda-Time 2.4 code seen below, note that we first parse the milliseconds using the default assumption of UTC. Then, secondly, we assign a time zone of Paris to adjust. Same moment in the timeline of the Universe, but different wall-clock time. For demonstration, we adjust again, to UTC. Almost always better to explicitly specify your desired/expected time zone rather than rely on an implicit default (often the cause of trouble in date-time work).
We need milliseconds to construct a DateTime. So take your input of seconds, and multiply by a thousand. Note that the result must be a 64-bit long as we would overflow a 32-bit int.
long input = 1_220_227_200L; // Note the "L" appended to long integer literals.
long milliseconds = ( input * 1_000L ); // Use a "long", not the usual "int". Note the appended "L".
Feed that count of milliseconds to constructor. That particular constructor assumes the count is from the Unix epoch of 1970. So adjust time zone as desired, after construction.
Use proper time zone names, a combination of continent and city/region. Never use 3 or 4 letter codes such as EST as they are neither standardized not unique.
DateTime dateTimeParis = new DateTime( milliseconds ).withZone( DateTimeZone.forID( "Europe/Paris" ) );
For demonstration, adjust the time zone again.
DateTime dateTimeUtc = dateTimeParis.withZone( DateTimeZone.UTC );
DateTime dateTimeMontréal = dateTimeParis.withZone( DateTimeZone.forID( "America/Montreal" ) );
Dump to console. Note how the date is different in Montréal, as the new day has begun in Europe but not yet in America.
System.out.println( "dateTimeParis: " + dateTimeParis );
System.out.println( "dateTimeUTC: " + dateTimeUtc );
System.out.println( "dateTimeMontréal: " + dateTimeMontréal );
When run.
dateTimeParis: 2008-09-01T02:00:00.000+02:00
dateTimeUTC: 2008-09-01T00:00:00.000Z
dateTimeMontréal: 2008-08-31T20:00:00.000-04:00
java.time
The makers of Joda-Time have asked us to migrate to its replacement, the java.time framework as soon as is convenient. While Joda-Time continues to be actively supported, all future development will be done on the java.time classes and their extensions in the ThreeTen-Extra project.
The java-time framework is defined by JSR 310 and built into Java 8 and later. The java.time classes have been back-ported to Java 6 & 7 on the ThreeTen-Backport project and to Android in the ThreeTenABP project.
An Instant is a moment on the timeline in UTC with a resolution of nanoseconds. Its epoch is the first moment of 1970 in UTC.
Instant instant = Instant.ofEpochSecond( 1_220_227_200L );
Apply an offset-from-UTC ZoneOffset to get an OffsetDateTime.
Better yet, if known, apply a time zone ZoneId to get a ZonedDateTime.
ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
It looks like your longs are seconds, and not milliseconds. Date constructor takes time as millis, so
Date d = new Date(timeInSeconds * 1000);
Only set the time in mills on Calendar object
Calendar c = Calendar.getInstance();
c.setTimeInMillis(1385355600000l);
System.out.println(c.get(Calendar.YEAR));
System.out.println(c.get(Calendar.MONTH));
System.out.println(c.get(Calendar.DAY_OF_MONTH));
// get Date
System.out.println(c.getTime());
Those are probably timestamps in seconds and not in milliseconds which is required for the java new Date(long) constructor. Just multiply them by 1000 and you should be allright.
The long values, most likely, correspond to Epoch timestamps, and the values are:
1220227200 = Mon, 01 Sep 2008 00:00:00 GMT
1220832000 = Mon, 08 Sep 2008 00:00:00 GMT
1221436800 = Mon, 15 Sep 2008 00:00:00 GMT
One can convert these long values to java.util.Date, taking into account the fact java.util.Date uses millisecs – as previously hinted, but with some flaw - like this:
// note: enforcing long literals (L), without it the values would just be wrong.
Date date = new Date(1220227200L * 1000L);
Now, to display the date correctly, one can use java.text.DateFormat as illustrated hereafter:
DateFormat df = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL);
df.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println("Wrong date time value: " + date);
System.out.println("Correct date time value: " + df.format(date));
Below are the results of displaying the converted long value to java.util.Date without
using and using the DateFormat:
Date wrong (off by 2 hours): Mon Sep 01 02:00:00 CEST 2008
Correct date : Monday, 1 September 2008 00:00:00 o'clock UTC
Try this:
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(1220227200 * 1000);
System.out.println(cal.getTime());
Try this with adjusting the date format.
long longtime = 1212580300;
SimpleDateFormat dateFormat = new SimpleDateFormat("MMddyyHHmm");
Date date = (Date) dateFormat.parseObject(longtime + "");
System.out.println(date);
Note: Check for 24 hours or 12 hours cycle.
1220227200 corresponds to Jan 15 1980 (and indeed new Date(1220227200).toString() returns "Thu Jan 15 03:57:07 CET 1970"). If you pass a long value to a date, that is before 01/01/1970 it will in fact return a date of 01/01/1970. Make sure that your values are not in this situation (lower than 82800000).
New Date(number) returns a date that's number milliseconds after 1 Jan 1970. Odds are you date format isn't showing hours, minutes, and seconds for you to see that it's just a little bit after 1 Jan 1970.
You need to parse the date according to the correct parsing routing. I don't know what a 1220227200 is, but if it's seconds after 1 JAN 1970, then multiply it to yield milliseconds. If it is not, then convert it in some manner to milliseconds after 1970 (if you want to continue to use java.util.Date).
Works for me. You probably want to multiplz it with 1000, since what you get are the seconds from 1970 and you have to pass the milliseconds from jan 1 1970
Because 1220227200 ms = 338,952 hours.
java.util.Date has constructor new Date(Long milliseconds) - Allocates a Date object and initializes it to represent the specified number of milliseconds since the standard base time known as "the epoch", namely January 1, 1970, 00:00:00 GMT.
So, in your case just remember 1 sec = 1000 millisec

Categories