normalize date using the deprecated Time class - java

the following method is written using the deprecated android Time class
// To make it easy to query for the exact date, we normalize all dates that go into
// the database to the start of the the Julian day at UTC.
public static long normalizeDate(long startDate) {
// normalize the start date to the beginning of the (UTC) day
Time time = new Time();
time.set(startDate);
int julianDay = Time.getJulianDay(startDate, time.gmtoff);
return time.setJulianDay(julianDay);
}
you can find this method here at line 47
please help me to understand it...
I tried different (unix, UTC) values for startDate argument such as 1464174000 and 1464433200 just to understand the output of the method but the method always return 1458000000 which is equivalent to:
03/15/2016 # 12:00am (UTC)
see the output here
so what is the purpose of the method if it always return the same value ?
i want to understand it so that i can write it again with the GregorianCalendar class that is not deprecated

From here
Callers must pass the time in UTC millisecond (as can be returned by toMillis(boolean) or normalize(boolean)) and the offset from UTC of the timezone in seconds (as might be in gmtoff).
So startDate should be in millisecond, not in second. Call with proper value. For example-
public static long normalizeDate(long startDate) {
// normalize the start date to the beginning of the (UTC) day
Time time = new Time();
time.set(1464181063013);
int julianDay = Time.getJulianDay(1464181063013, time.gmtoff);
return time.setJulianDay(julianDay);
}
I hope it will give you a different result.

Related

Return ISO-8601 time format in days from Epoch time in Java

I have some Java code which returns the ISO-8601 time format from a given epoch time.
public String getISO8601(String epochTime) {
long epoch = Long.parseLong(epochTs);
ZoneId zone = ZoneId.of("Europe/London");
LocalDate then = Instant.ofEpochMilli(epoch).atZone(zone).toLocalDate();
LocalDate today = LocalDate.now(zone);
Period diff = Period.between(then, today);
return diff.toString();
}
When I pass epochTime to it: 1512259200000
This epoch time is: Sun 2017-12-03 00:00:00
So the method getISO8601 will return: P1Y
This is great! But is there any way I can make sure it will always and only return in days... for example: P365D (instead of: P1Y)
Unfortunately Period doesn't allow the units to be specified, but you can use the until method to handle this, specifying you want the difference in days:
public static Period getPeriodInDaysBetween(LocalDate from, LocalDate to) {
int days = (int) from.until(to, ChronoUnit.DAYS);
return Period.ofDays(days);
}
Use that instead of Period.between and it'll do what you want, I believe.
(The first line is equivalent to the ChronoUnit.DAYS.between(date1, date2) in MS90's answer. Use whichever you find more readable.)
Sure, take a look at following code:
public static long countDays(LocalDate date1, LocalDate date2) {
long daysInAPeriod = ChronoUnit.DAYS.between(date1, date2);
return daysInAPeriod;
}
Period has a getDays method which returns an int number of days in the Period.

jodatime DateTime millis cannot be set with actual epoch millis

I'm looking for a reasonable way to set the value of jodatime's DateTime millis. While debugging in Intellij IDEA (v15), I'm looking at the following code:
public String getDayOfWeek(String timezone) {
DateTime now = DateTime.now(DateTimeZone.forID(timezone));
return now.dayOfWeek().getAsText();
}
If I breakpoint the return statement for the purpose of mutating the value of now by changing the millis field of the DateTime instance to reflect a different (valid) epoch time with millis, Intellij errors that the value I'm attempting to set exceeds the capacity of int. It makes sense since epoch with millis is 13-digits and IIRC int can only store 2^32-1.
There isn't a visible field in the DateTime instance for epoch time without millis. I can successfully set the value with the 10-digit epoch time without millis, but clearly that's not going to evaluate properly; I only mention it to say that I'm able to set within-range values in the debugger successfully.
What options are there? Alternately, is there a more elegant way with jodatime to derive the current day of the week that also allows me to mutate the value? The caller doesn't assign the return value, rather, simply uses it for comparison. I don't want to scrap jodatime since this method is part of a quite large class of methods that all use it.
Thanks in advance for your time.
Maybe you ran into this issue because the value used was interpreted as an int instead of a long? You can use one of the DateTime constructors that takes a long parameter to specify the date and time in milliseconds. For example:
import org.joda.time.*;
import org.joda.time.format.*;
public class JodaTimeMillis {
public static void main(final String[] arguments) {
new JodaTimeMillis().run();
}
private void run() {
DateTimeZone timeZone = DateTimeZone.forID("Europe/Amsterdam");
String pattern = "MM/dd/yyyy HH:mm:ss.SSS";
DateTimeFormatter dateTimeFormatter = DateTimeFormat.forPattern(pattern);
for (int milliseconds = 619; milliseconds < 629; milliseconds++) {
DateTime dateTime = new DateTime(1234567890000L + milliseconds, timeZone);
System.out.println(milliseconds + ": " + dateTimeFormatter.print(dateTime));
}
}
}
This gives the following output (on my laptop), which shows that the milliseconds part can be specified:
619: 02/14/2009 00:31:30.619
620: 02/14/2009 00:31:30.620
621: 02/14/2009 00:31:30.621
622: 02/14/2009 00:31:30.622
623: 02/14/2009 00:31:30.623
624: 02/14/2009 00:31:30.624
625: 02/14/2009 00:31:30.625
626: 02/14/2009 00:31:30.626
627: 02/14/2009 00:31:30.627
628: 02/14/2009 00:31:30.628
Do you want to run tests from the debugger? You could also consider using unit tests.

Long To XMLGregorianCalendar and back to Long

I am trying to convert from millisecond time stamp to XMLGregorianCalendar and back, but I seem to be getting wrong results. Am I doing something wrong? It seems I am gaining days.
// Time stamp 01-Jan-0001 00:00:00.000
Long ts = -62135740800000L;
System.out.println(ts);
System.out.println(new Date(ts)); // Sat Jan 01 00:00:00 PST 1 .. Cool!
// to Gregorian Calendar
GregorianCalendar gc = new GregorianCalendar();
gc.setTimeInMillis(ts);
// to XML Gregorian Calendar
XMLGregorianCalendar xc = DatatypeFactory.newInstance().newXMLGregorianCalendar(gc);
// back to GC
GregorianCalendar gc2 = xc.toGregorianCalendar();
// to Timestamp
Long newTs = gc2.getTimeInMillis();
System.out.println(newTs); // -62135568000000 .. uh?
System.out.println(new Date(newTs)); // Mon Jan 03 00:00:00 PST 1 .. where did the extra days come from?
Interesting - it works fine for values down to (about) -10000000000000L (and positive values) but larger negative values become inconsistent.
If you print out gc, xc, and gc2, you can see where the problem arises (the conversion from XMLGregorianCalendar to GregorianCalendar
gc: java.util.GregorianCalendar[time=-62135740800000 ... DAY_OF_WEEK=7
xc: 0001-01-01T08:00:00.000Z
gc2: java.util.GregorianCalendar[time=? ... DAY_OF_WEEK=5
If you print out the fields of xc, you get 1,1,1.
System.out.println(xc.getYear());
System.out.println(xc.getMonth());
System.out.println(xc.getDay());
For gc2, you get 1,0,1 (which matches xc, because months are zero-based in GregorianCalendar)
System.out.println(gc2.get(gc2.YEAR));
System.out.println(gc2.get(gc2.MONTH));
System.out.println(gc2.get(gc2.DAY_OF_MONTH));
However, adding these 3 println calls changes the output from printing out gc2! - the time=? output from gc2 changes to time=-62135568000000 - so some calculation has been triggered by querying the GregorianCalendar object; the areFieldsSet property also changes from false to true.
The timezones of the two GregorianCalendars are different, but this does not account for the error, which persists even if you set explicit TimeZone and Locale.
I believe here is the problem. Per documentation, toGregorianCalendar() relies on the GregorianCalendar corresponding defaults for conversion when there is any field missing.
If you try:
Date date = new Date();
long ts = date.getTime(); //in place of your input
and run your code, you should find, both to and from conversion working fine.
If you want your toGregorianCalendar() with custom provide inputs as in your example, please use toGregorianCalendar(TimeZone,Locale,Defaults) and supply the updated defaults to be used in conversion.

How to create a joda time duration from java.sql.Time?

Hello I have this excerpt of code:
end = new DateTime(mergeToDateTime(this.endDate, this.empEndTime));
Duration extraTime = new Duration(this.preTime.getTime()); //add the first 30 mins
extraTime = extraTime.plus(new Duration(this.postTime.getTime())); //add the second 30 mins
end = end.plus(extraTime); // extraTime = -3600?
When I look in the debugger my durations are always coming up negative. I have no idea why this is, even though according to the API, it is possible to create a duration out of the a long type, hence the getTime(). (preTime and postTime are java.sql.Time types)
I guess your instances of java.sql.Time were created in such a way that their millisecond values include timezone offset.
For example, deprecated java.sql.Time(int hour, int minute, int second) constructor takes offset of the current timezone into account:
System.out.println(new Time(1, 0, 0).getTime()); // Prints -7200000 in UTC+3 timezone
It looks like timezone offset is introduced by JDBC driver, and it can be easily compensated by converting java.sql.Time to LocalTime (and vice versa):
LocalTime lt = new LocalTime(time);
Then you can convert LocalTime to duration:
Duration d = new Duration(lt.getMillisOfDay());
Aren't you starting out wrong when you use an instant in time as duration? The constructor signature you are using is Duration(long duration), not Duration(long startInstant) -- there is no such constructor, in fact.

Comparing only the time component of Date

Consider the following code to only determine if the time component of one Date object is before the time component of another Date object:
private boolean validStartStopTime( Date start, Date stop ) {
Calendar startCal = Calendar.getInstance();
Calendar stopCal = Calendar.getInstance();
startCal.clear();
stopCal.clear();
startCal.setTime( start );
stopCal.setTime( stop );
startCal.set( Calendar.YEAR, 2011 );
stopCal.set( Calendar.YEAR, 2011 );
startCal.set( Calendar.MONTH, 1 );
stopCal.set( Calendar.MONTH, 1 );
startCal.set( Calendar.DAY_OF_YEAR, 1 );
stopCal.set( Calendar.DAY_OF_YEAR, 1 );
return startCal.before( stopCal );
}
Would this insure that time comparison is correct? Is there a better alternative (Joda is not an option)? I believe that this is equivalent to setting the Calendar objects to current date/time and manually copying over the hour, minutes, and milliseconds component. You can assume that timezone are the same.
EDIT: To clarify what I mean by comparing only the time component of a Date object. I mean that when looking specifically at the time portion, the start time is before the stop time. The date portion is ABSOLUTELY irrelevant (in that start="Jan 2 20011 10AM" and end="Jan 1 2011 11AM" is perfectly fine), if I had a choice I'd simply use something that contained just the time but a Date object is what I'm given. I'd like to not write a sequence of if-else which is why I have the approach above but I welcome a cleaner/better approach.
Your code should work fine. You could also format just the time components in a zero-based string notation and compare them lexicographically:
public static boolean timeIsBefore(Date d1, Date d2) {
DateFormat f = new SimpleDateFormat("HH:mm:ss.SSS");
return f.format(d1).compareTo(f.format(d2)) < 0;
}
[Edit]
This is assuming that the dates have the same timezone offset. If not you'll have to adjust them manually beforehand (or as part of this function).
There are 86,400,000 milliseconds in a day, why not just use that to figure it out?
You could just mod timeInMilliseconds with that number and compare the results.

Categories