Calendar give wrong timestamp on adding one day - android

I am trying to add one day to calendar date but i am getting wrong output.
Below code i am using.
var cal2= Calendar.getInstance()
cal2!!.timeInMillis=cal.timeInMillis
Log.e("Time1",""+cal.timeInMillis);
cal2.add(Calendar.DATE, 1)
Log.e("Time2",""+cal2.timeInMillis);
Time1: 1526478465( Wednesday, 16 May 2018 19:17:45)
Time1: 1612878465(Tuesday, 9 February 2021 19:17:45 )

Assuming your cal.timeInMillis has proper value (say today's date), your code works fine:
var cal = Calendar.getInstance() <-- Assumption
var cal2 = Calendar.getInstance()
cal2!!.timeInMillis=cal.timeInMillis
println("Time1: "+cal.timeInMillis);
cal2.add(Calendar.DATE, 1)
println("Time2: "+cal2.timeInMillis);
Running above code gives following output:
Time1: 1527159971747 (Thursday, May 24, 2018 11:06:11.747 AM)
Time2: 1527246371747 (Friday, May 25, 2018 11:06:11.747 AM)

You’re somehow confusing seconds and milliseconds since the epoch. 1 526 478 465 is seconds. If you treat them as milliseconds, you get January 18, 1970 4:01:18 PM UTC. If you add 1 day to that, you get the next value you mention (I got 1 612 878 000, it comes close). When in turn you interpret 1 612 878 465 as seconds, you get February 9, 2021 1:47:45 PM UTC. This is the same as the date-time you mention, Tuesday, 9 February 2021 19:17:45, if I assume you’re at offset +05:30 (like Asia/Kolkata or Asia/Colombo time zone).
Since there are 1000 milliseconds in a second, your confusion has caused you to add 1000 days to your date instead of 1 day.
Tip: 10 digit values are usually seoncds. 13 digit values are usually milliseconds.

Related

Chinese New Year Date on Android

How one could get Chinese New Year Date on Android?
Since API level 24 Android has Chinese Calendar class.
https://developer.android.com/reference/android/icu/util/ChineseCalendar
However, doing it like this returns wrong date (Feb 12 for 2023).
val chinese = ChineseCalendar.getInstance()
chinese.set(ChineseCalendar.MONTH, 0)
chinese.set(ChineseCalendar.DAY_OF_MONTH, 1)
I was able to get Gregorian date for Chinese new year in the following way. Getting Chinese calendar is done using simple instantiation ChineseCalendar(). No need to call getInstance().
val chinese = ChineseCalendar()
chinese.set(ChineseCalendar.MONTH, 0)
chinese.set(ChineseCalendar.DAY_OF_MONTH, 1)
println("chinese " + chinese.time.toString())
In the logs I got
chinese Sun Jan 22 13:24:41 GMT+02:00 2023
You can also add year to get next new year date, like this
chinese.add(ChineseCalendar.YEAR, 1)
and get
chinese Sat Feb 10 13:27:41 GMT+02:00 2024

Calendar returns wrong week

So I need to get time in milliseconds for Monday of this week and time in milliseconds of Sunday for this week and with code below it worked fine till I installed app on emulator and if I set time to Sunday it returns Jun 18 - Jun 24, but on Samsung Galaxy s5 it returns Jun 11 - Jun 17 <- this is how it should show Am I doing something wrong?
getMondayTime method returns time in milliseconds for monday
private fun getMondayTime(): Long{
val calendar = Calendar.getInstance()
calendar.timeInMillis = System.currentTimeMillis()
calendar.firstDayOfWeek = Calendar.MONDAY
calendar.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY)
calendar.set(Calendar.HOUR_OF_DAY, 0)
calendar.set(Calendar.MINUTE, 0)
calendar.set(Calendar.SECOND, 0)
calendar.set(Calendar.MILLISECOND, 0)
return calendar.timeInMillis
}
getSundayTime returns time in milliseconds for sunday
private fun getSundayTime(): Long {
val calendar = Calendar.getInstance()
calendar.timeInMillis = System.currentTimeMillis()
calendar.firstDayOfWeek = Calendar.MONDAY
calendar.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY)
calendar.set(Calendar.HOUR_OF_DAY, 22)
calendar.set(Calendar.MINUTE, 0)
calendar.set(Calendar.SECOND, 0)
calendar.set(Calendar.MILLISECOND, 0)
return calendar.timeInMillis
}
Here I'm putting all this time into places
fun generateWeek(): Week{
val format = SimpleDateFormat("MMM d", Locale.ENGLISH)
val mondayTime = getMondayTime()
val sundayTime = getSundayTime()
val label = "${format.format(mondayTime)} - ${format.format(sundayTime)}"
return Week(label, mondayTime, sundayTime)
}
java.time
I am sorry I cannot write Kotlin (if that’s your language?) so I will have to trust you to translate from Java. The modern solution is:
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("MMM d", Locale.ENGLISH);
// Time zone is crucial for controlling which week we get.
ZoneId zone = ZoneId.of("America/Lower_Princes");
WeekFields wf = WeekFields.ISO; // Monday is first day of week
LocalDate today = LocalDate.now(zone);
ZonedDateTime mondayTime = today.with(wf.dayOfWeek(), 1).atStartOfDay(zone);
ZonedDateTime sundayTime = today.with(wf.dayOfWeek(), 7)
.atTime(LocalTime.of(22, 0))
.atZone(zone);
String label = mondayTime.format(dateFormatter) + " - " + sundayTime.format(dateFormatter);
System.out.println("Label: " + label);
System.out.println("Monday time in millis: " + mondayTime.toInstant().toEpochMilli());
System.out.println("Sunday time in millis: " + sundayTime.toInstant().toEpochMilli());
Running just now (Monday) this printed:
Label: Jun 18 - Jun 24
Monday time in millis: 1529294400000
Sunday time in millis: 1529892000000
At time of writing it is still Sunday in very few time zones in the Pacific. So I also tried one of those:
ZoneId zone = ZoneId.of("Pacific/Niue");
Then I got last week:
Label: Jun 11 - Jun 17
Monday time in millis: 1528714800000
Sunday time in millis: 1529312400000
So specifying the correct time zone is crucial for getting the week you want. I suspect that this was the issue in your question: if your emulator is set to using a time zone where it was already Monday when you ran your code, it would give you the coming week, as you observed.
I am using and recommending java.time, the modern Java date and time API.
Question: Can I use java.time on Android?
Yes, java.time works nicely on older and newer Android devices. It just requires at least Java 6.
In Java 8 and later and on newer Android devices (from API level 26, I’m told) the modern API comes built-in.
In Java 6 and 7 get the ThreeTen Backport, the backport of the new classes (ThreeTen for JSR 310; see the links at the bottom).
On (older) Android use the Android edition of ThreeTen Backport. It’s called ThreeTenABP. And make sure you import the date and time classes from org.threeten.bp with subpackages.
If you are opposed to depending on an external library, even a future-proof one like ThreeTenABP — I mean, it’s developed by the same folks that developed java.time for Java and it only contains functionality that will also be included in core Java once you upgrade to API level 26 or higher — in that case you can probably solve your issue by passing the correct TimeZone object to the Calendar.getInstance(TimeZone) method (I haven’t tried). TimeZone is one more of the outdated date and time classes.
Links
Oracle tutorial: Date Time explaining how to use java.time.
Java Specification Request (JSR) 310, where java.time was first described.
ThreeTen Backport project, the backport of java.timeto Java 6 and 7 (ThreeTen for JSR-310).
ThreeTenABP, Android edition of ThreeTen Backport
Question: How to use ThreeTenABP in Android Project, with a very thorough explanation.
Calendar.getInstance(TimeZone) method documentation

Android studio double to date format

I'm making a project on android studio.
I must convert a number into an hour, minutes and seconds date.
The number is: 0,18865386
The result must be: 04:31:40
I've obtained this date whit excel (used for test calc) just changing the cell format to HOURS but i don't understand how to calculate it.
Any solutions?
1 corresponds to 24 hours.
In hours: 0,18865386 means 24 x 0,18865386 ~= 4,5 hours which corresponds to your 04:31:40.
If you need more precision, e.g. in seconds:
The number of seconds in a day = 24 x 60 x 60 = 86400.
Then 0,18865386 means 86400 x 0,18865386 = 16300 seconds = 04:31:40.

JodaTime period returns unexpected results

I am trying to calculate the difference between any two given times in an android app. To accomplish this task I was using JodaTime and the Period class along with Period's getYears(), getDays(), getHours(), getMinutes(), and getSeconds() methods. However, I realized that it is giving what seems the be the absolute difference between each element of the date. For example, calling my function on the dates 2017-01-29 00:00:00 (yyyy-MM-dd HH:mm:ss) and 2018-01-28 00:00:00 will return:
0 years
2 days
0 hours
0 minutes
0 seconds
when it should return 364 days along with zeros in every other section. Of course, it is an android app so I am not printing them, I am handling the display separately. I was able to do this on my computer using LocalDateTime and Duration.between, but I cannot use these classes here. I am looking for either a fix for my current method (which is below) or suggestions for a completely new approach. Thank you in advance.
My current function:
public int[] getDifference(DateTime start, DateTime end){
Period p = new Period(start, end);
int[] differences = new int[5];
differences[0] = p.getYears();
differences[1] = p.getDays();
differences[2] = p.getHours();
differences[3] = p.getMinutes();
differences[4] = p.getSeconds();
return differences;
}
Why would you expect 364 days? Read the class doc for Period.
public int getDays()
Gets the days field part of the period.
The “field part” is the key here. A Period is a number of years, months, weeks, days, hours, minutes, seconds, and milliseconds. For example, a year and a half would have two parts, a years part of 1 and a months part of 6.
Your output skipped over the months part and the weeks part.
DateTime start = new DateTime ( 2017 , 1 , 29 , 0 , 0 , DateTimeZone.UTC );
DateTime stop = new DateTime ( 2018 , 1 , 28 , 0 , 0 , DateTimeZone.UTC );
Period p = new Period ( start , stop );
int[] differences = new int[ 7 ];
differences[ 0 ] = p.getYears ();
differences[ 1 ] = p.getMonths ();
differences[ 2 ] = p.getWeeks ();
differences[ 3 ] = p.getDays ();
differences[ 4 ] = p.getHours ();
differences[ 5 ] = p.getMinutes ();
differences[ 6 ] = p.getSeconds ();
System.out.println ( "differences: " + Arrays.toString ( differences ) );
When run, we see eleven months, four weeks, and two days. Running Joda-Time 2.8.2 in Java 8 Update 121 on macOS El Capitan.
differences: [0, 11, 4, 2, 0, 0, 0]
You might think of calling toStandardDays. But doing so results in an exception (java.lang.UnsupportedOperationException) saying: “Cannot convert to Days as this period contains months and months vary in length”.
java.time
FYI: The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
In java.time, a span of time unattached to the timeline is represented as either years-month-days in java.time.Period or hours-minutes-seconds-nanoseconds in java.time.Duration.
The LocalDate class represents a date-only value without time-of-day and without time zone.
The java.time classes eschew constructors, using factory methods instead.
LocalDate start = LocalDate.of ( 2017 , 1 , 29 );
LocalDate stop = LocalDate.of ( 2018 , 1 , 28 );
Period period = Period.between ( start , stop );
System.out.println ( "period.toString(): " + period );
The toString generates a piece of text in standard ISO 8601 format for durations. We see here eleven months and thirty days. Obviously Joda-Time and java.time count differently. Here we see different results. Joda-Time counts weeks while java.time does not.
period.toString(): P11M30D
Try replacing
Period p = new Period(start, end);
with
Period p = new Period(start, end, PeriodType.yearMonthDayTime());
You should also set the appropriate period type because you want a specific normalization to years, days, hours, minutes and seconds only, see also javadoc.
LocalDateTime start = new LocalDateTime(2017, 1, 29, 0, 0);
LocalDateTime end = new LocalDateTime(2018, 1, 28, 0, 0);
Period p = new Period(start, end, PeriodType.yearDayTime().withMillisRemoved());
System.out.println(p); // P364D (what you expected)
This example would also work with the type DateTime for start and end.
Please note that this code example (as the class Period of Joda-Time itself) cannot be fully migrated to new java.time-API contained in Java-8 because latter API cannot handle durations with date AND time components. It can also not specify the period type i.e. cannot control the normalization as PeriodType does.

JodaTime will always change to 2015 if withYear set to 2016

This is really driving me crazy. The code below
DateTime dt = new DateTime()
.withYear(2014)
.withWeekOfWeekyear(52)
.withDayOfWeek(1);
DateTimeFormatter dateTimeFormatter = DateTimeFormat.forPattern("d MMM yyyy");
String firstDayOfWeek = dateTimeFormatter.print(dt);
Log.v(FILE_NAME,"display date? " + firstDayOfWeek);
dt = new DateTime()
.withYear(2015)
.withWeekOfWeekyear(52)
.withDayOfWeek(1);
String lastDayOfWeek = dateTimeFormatter.print(dt);
Log.v(FILE_NAME,"display date? " + lastDayOfWeek);
dt = new DateTime()
.withYear(2016)
.withWeekOfWeekyear(52)
.withDayOfWeek(1);
lastDayOfWeek = dateTimeFormatter.print(dt);
Log.v(FILE_NAME,"display date? " + lastDayOfWeek);
Somehow will always output:
display date? 22 Dec 2014
display date? 21 Dec 2015
display date? 21 Dec 2015
As you can see, the last display date should display 2016, not 2015. It seems that everytime I set withYear to 2016, it will magically change to 2015. Is this a bug or am I doing something wrong? I have cleaned and rebuild my project many times but the output is the same.
The method withYear(...) does not do what you think because it uses the standard calendar year and not the year of week date as described in ISO-8601-paper. Please compare following two snippets. Only the second one does what you need:
DateTime dt = new DateTime().withYear(2016).withWeekOfWeekyear(52).withDayOfWeek(1);
System.out.println("joda=" + dt); // joda=2015-12-21T18:26:12.776+01:00
DateTime dt2 =
new DateTime().withWeekyear(2016).withWeekOfWeekyear(52).withDayOfWeek(1);
System.out.println("joda=" + dt2); // joda=2016-12-26T18:27:59.606+01:00
See also the documentation. The fine difference between calendar year and weekbased year is only noticeable at the end or start of a year (like today).
Explained in detail the behaviour:
If choosing new DateTime() for today, the second of January 2017 and then setting the calendar year to 2016 results in: 2016-01-02. But this date is in week-of-year 53 belonging to week-based-year 2015. This 53rd week starts on 2015-12-28, so the expression withWeekOfWeekyear(52) will go back one week to 2015-12-21 (what you observe in first case).

Categories

Resources