Can convert date to long but long is too big? - java

I'm very confused right now.
I have a GregorianCalendar object which I give a specific date (Jan 1st 2010).
Calendar:
Calendar c = new GregorianCalendar();
c.set(2010, 0, 1);
System.out.println(c.getTime());
System.out.println(c.getTimeInMillis());
Output:
Fri Jan 01 13:12:57 CET 2010
1262347977927
Now when I try to create a long and store this number in it, the number is actually too big for my variable.
Storing in variable:
long timeStamp = 1262347977927;
// ERROR: The literal 1262347977927 of type int is out of range
But when I store the result directly into my variable, it works just fine.
Directly storing:
long timeStamp = c.getTimeInMillis();
System.out.println(timeStamp);
Output:
1262348451631
Why is the long that I get too big to be a long, yet not too long to be a long? I'm confused.
I'm using Java 6 and Eclipse Indigo if anyone would want to know.
EDIT: Thanks for all the instant answers... I feel really stupid now :p

You just have to add a L after the literal:
long timeStamp = 1262347977927L;

Always refer to the docs, Primitive Data Types:
An integer literal is of type long if it ends with the letter L or l;
otherwise it is of type int. It is recommended that you use the upper
case letter L because the lower case letter l is hard to distinguish
from the digit 1.

User the L at the end of the number:
long timeStamp = 1262347977927L;
It defines the Number as Long.

You must append an L or l
long timeStamp = 1262347977927L;
literal to the assigned value otherwise an integer value is assumed by the compiler
The former is preferable as the latter looks like a 1!

No 1262347977927 is not big enough for a long number (which is 8 bytes).
Make it like this:
long timeStamp = 1262347977927L;
L for long declaration.
Reason is that in Java by default all numbers are treated as int type unless you put switches like L in the end.
Or simple:
long timeStamp = c.getTimeInMillis()

Change
long timeStamp = 1262347977927;
to
long timeStamp = 1262347977927L;
Note that you need to suffix 'L' (preferred) or 'l' (suffixing this can lead to difficult to read code; there's a a java puzzler entry related to this) at the end .

It's not telling you that 1262347977927 can't fit into a long, it's telling you that it can't construct an int constant of value 1262347977927, before it even tries to assign it into the long variable. Notice how timeStamp is never mentioned in the error:
The literal 1262347977927 of type int is out of range
Use L after the number to mark it as a long constant, then you can assign it without problems:
long timeStamp = 1262347977927L;

Try appending 'L' after your number while assigning it to long variable.

Related

Strip seconds and milliseconds from System.currentTimeMillis value

Suppose I have a System.currentTimeMillis() value as a long number.
How do I modify it to match the instant when last minute started? I.e., zero out seconds and milliseconds.
I would prefer to not use magic constants. Using java.time is fine.
I agree with the answers recommending java.time, but it can be done yet simpler as in those answers:
long lastWholeMinute = Instant.now().truncatedTo(ChronoUnit.MINUTES).toEpochMilli();
This just gave 1517940060000. Of course, if it makes sense for you to keep the Instant object, by all means do that rather than converting to a naked primitive long.
If your long value was one you had stored rather than the time now, it’s quite similar:
long someEpochMilliValue = 1_517_941_234_567L;
long lastWholeMinute = Instant.ofEpochMilli(someEpochMilliValue)
.truncatedTo(ChronoUnit.MINUTES)
.toEpochMilli();
Using java.time is probably the easiest way. You could use withNano and withSecond, like
java.time.ZonedDateTime zdt = java.time.ZonedDateTime.now().withNano(0).withSecond(0);
long millis = zdt.toInstant().toEpochMilli();
Since the value is in milliseconds, if we assume an idealized day (no leap seconds, etc.), then given l you could do it by simply removing the value of l % 60000L from it. I realize that's a magic constant, but it's truly a constant, there are always going to be 60,000 milliseconds in a minute. I'd give it symbolic name:
private static long SIXTY_SECONDS_IN_MS = 60000L;
and not worry about it. Then it's:
long l = /*...your number...*/;
l = l - (l % SIXTY_SECONDS_IN_MS);
Why this works: The Epoch value is from midnight Jan 1st 1970, and so at 0L, 60000L, 120000L, etc., the seconds and milliseconds of an idealized day based on that value are 0. So we use the remainder operator (%) to isolate the part of the value that would remain if we divided by 60000L and remove it. Thus the resulting value, again assuming idealized days, has 0 for seconds and milliseconds. It also works across timezones if we assume all timezones are going to be at whole-minute offsets to UTC. I've only ever heard of timezones that were multiples of hours or half-hours offset from UTC ("GMT plus five hours", "GMT plus 5.5 hours"), never (say) "GMT plus five hours seven minutes and 20 seconds". (And indeed, the standard notation for timezome offsets, +0600 or similar, only includes hours and minutes, not fractional minutes.)
Live Example:
import java.time.*;
public class Example
{
private static long SIXTY_SECONDS_IN_MS = 60000L;
public static void main (String[] args) throws java.lang.Exception
{
long l = System.currentTimeMillis();
l = l - (l % SIXTY_SECONDS_IN_MS);
System.out.println("l = " + l);
// Checking the result
LocalDateTime dt = Instant.ofEpochMilli(l).atZone(ZoneId.systemDefault()).toLocalDateTime();
System.out.println(dt);
System.out.println(dt.getSecond()); // 0
System.out.println(dt.getNano()); // 0
}
}
Still, though, if that constant violates the terms of the question such that you think I shouldn't have answered, let me know and I'll delete the answer. :-)

Convert time format to long variable in Java

Is there a possibility to convert a time format which is represented as a string (00:00:000) to long variable.
I'm not sure what do you mean by Convert to currentTimeMillis() or some float variable., but if you are simply looking to convert the given time to long then you can do something like this using simple split:
String timeString = "01:00:100";
int multiplier[] = {3600000, 60000, 100};
String splits[] = timeString.split(":");
long time = 0;
for (int x = 0; x < splits.length; x++) {
time += (Integer.parseInt(splits[x]) * multiplier[x]);
}
System.out.println(time);
Here, the time is being represented in Milliseconds.
Also, this is plain Java and nothing Android specific.
That simply doesn't make much sense.
currentTimeMillis() returns the difference, measured in milliseconds, between the current time and midnight, January 1, 1970 UTC.
In other words: the result of a call to that method represents a full blown time stamp; not only hh::mm:sss as in your example; but all of that plus year, month, ...
Thus the answer here: you should step back and clarify for yourself what your actual requirements are.

TOD clock time to java.util.Date or milliseconds

I have a database table, which is filled with data from a mainframe via ETL.
One column of that table is called "TOD" as in Time-Of-Day.
This columns stores values such as :
"CAE7631DC43DC686"
"CAE7631C4AC6DC0B"
"CAE6216DF2BC0D04"
"CAE621D8F9916E8E"
all these values are around Feb 10th 2013 and Feb 11th 2013.
now, on mainframe, this is a time-date representation (TOD clock).
it represents the time past from 01.01.1900 in macroseconds (1/1 000 000 of a second).
What I need is a java library / method / algorithm implementation that could convert these strings to java.util.Date's.
Found these sites on the web :
http://paul.saers.com/Tod_howto.html
http://www.longpelaexpertise.com.au/toolsTOD.php
This page explains how to calculate it, but it's a little too much for me.
I'm sure I'd do some errors somewhere.
So, my question is; do you know about a library (Joda Time ?) that I could use ?
I need to convert these value to a java.util.Date and a Date object to a string representation, (like "CAE621D8F9916E8E").
Thanks in advance.
In my use case I have a getter method that directly reads the 8 bytes TOD as byte array and translates it into a long, but here to adhere to the poster:
BigInteger bi = new BigInteger ("CAE7631DC43DC686", 16); // no strip off of 686
long tod = bi2.longValue();
I used the following to avoid the BigDecimal calculation overhead:
tod = tod >>> 12; // remove rightmost 3 bytes and replace with zeros
tod = tod - 2208988800000000l; // substract 1970
tod = tod/1000; // make millis out of micros
// timeformatter and dateformatter without Joda
SimpleDateFormat timeFormatter = new SimpleDateFormat("HH:mm:ss.SS z Z", Locale.getDefault());
SimpleDateFormat dateFormatter = new SimpleDateFormat("dd.MM.yyyy", Locale.getDefault());
// Display
System.out.println(timeFormatter.format(new Date(tod)));
System.out.println(dateFormatter.format(new Date(tod)));
The output will be:
22:59:46.420 CET +0100
10.02.2013
Step by step, using Joda:
Data used in the calculation can be found on the website you referred to The other reference you gave states that TOD is expressed in UTC
// we start with your string minus the three last digits
// which are some internal z/Series cruft
BigInteger bi = new BigInteger ("CAE7631DC43DC", 16); // 686 stripped off
// then, from tables the website we get the TOD value for start of epoch
// here also, minus the three last digits
BigInteger startOfEpoch70 = new BigInteger ("7D91048BCA000", 16); // 000 stripped off
// using that we calculate the offset in microseconds in epoch
BigInteger microsinepoch = bi.subtract(startOfEpoch70);
// and reduce to millis
BigInteger millisinepoch = microsinepoch.divide(new BigInteger("1000"));
// which we convert to a long to feed to Joda
long millisinepochLong = millisinepoch.longValue();
// Et voila, the result in UTC
DateTime result = new DateTime(millisinepochLong).withZone(DateTimeZone.UTC);
// Now, if you want a result in some other timezone, that's equally easy
// with Joda:
DateTime result2 = result.toDateTime(DateTimeZone.forID("EET"));
System.out.println("The result is " + result + " or represented in timezone EET "
+ result2);
Which gives this output:
The result is 2013-02-10T21:59:46.420Z or represented in timezone
EET 2013-02-10T23:59:46.420+02:00
The "cruft" I refer to is explained as follows:
We skip the last 12 bits (normally,some of these bits are used by MVS to tell what processor was used to read the TOD clock and what LPAR was active).
Of course, instead of brutally snipping these bytes off the string, one could also do
bi = bi.divide(new BigInteger("1000", 16));
as dividing by hex 1000 will also get rid of the last 12 bits.
EDIT: as Mehmet pointed out in the comments, TOD is in UTC and this means that the resulting DateTime should be told so. For convenience I also showed how to transpose that DateTime to another time zone (using EET as an example)
Parse your hex date using BigInteger:
new BigInteger("CAE7631DC43DC686", 16);
Then do the necessary conversions to the Unix epoch using the various methods offered by BigInteger (multiply, ...).

Convert String (representing decimal number) to long

I've googled around a bit but could not find examples to find a solution. Here is my problem:
String s = "100.000";
long l = Long.parseLong(s);
The 2nd line of code which tries to parse the string 's' into a long throws a NumberFormatException.
Is there a way around this? the problem is the string representing the decimal number is actually time in milliseconds so I cannot cast it to int because I lose precision.
You could use a BigDecimal to handle the double parsing (without the risk of precision loss that you might get with Double.parseDouble()):
BigDecimal bd = new BigDecimal(s);
long value = bd.longValue();
as i don't know is your 100.000 equals 100 or 100 000
i think safest solution which i can recommend you will be:
NumberFormat nf = NumberFormat.getInstance();
Number number = nf.parse("100.000");
long l = number.longValue();
'long' is an integer type, so the String parse is rejected due to the decimal point. Selecting a more appropriate type may help, such as a double.
Just remove all spaceholders for the thousands, the dot...
s.replaceAll(".","");
You should use NumberFormat to parse the values
We can use regular expression to trim out the decimal part. Then use parseLong
Long.parseLong( data.replaceAll("\..*", ""));
If you don't want to loose presision then you should use multiplication
BigDecimal bigDecimal = new BigDecimal("100.111");
long l = (long) (bigDecimal.doubleValue() * 1000);<--Multiply by 1000 as it
is miliseconds
System.out.println(l);
Output:
100111

About GregorianCalendar : the same input but different output in java

I want to use milliseconds to set a new date in my program,but it doesnt work. Is there anybody can tell me why it doesnt work?
Calendar r_1 = new GregorianCalendar(2011,0,1);
r_1.add(Calendar.DAY_OF_MONTH,2);
System.out.println(r_1.getTime());
long date_1 = r_1.getTimeInMillis() + 2*24*60*60*1000;
r_1.setTimeInMillis(startTime1);
System.out.println(r_1.getTime());
It works both very correct , but if i change the day from 2 to 25,then it doenst work .
----------the output is correct ,it is 2011/01/26 ----------
Calendar r_1 = new GregorianCalendar(2011,0,1);
r_1.add(Calendar.DAY_OF_MONTH,25);
System.out.println(r_1.getTime());
-----------the output is incorrect now ,it is 2010/12/07------
long date_1 = r_1.getTimeInMillis() + 25*24*60*60*1000;//i have change 2 to 25
r_1.setTimeInMillis(startTime1);
System.out.println(r_1.getTime());
Thanks
The expression 25*24*60*60*1000 is an integer, and you have overflowed the size of an integer, creating a negative number.
Your expression is 2,160,000,000 milliseconds. The largest value an int can hold is 2,147,483,647.
To fix this, you have to force the expression to be a long, as follows
25L*24*60*60*1000
25*24*60*60*1000 is too large to fit in an int.
Try 25L*24*60*60*1000 which is a long constant.
Try something like that:
final long k = 25*24*60*60*1000L;
long date_1 = r_1.getTimeInMillis() + k;

Categories

Resources