Calendar returns wrong week - android

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

Related

Calling last Friday in November every year

I have a code that manually calls the last Friday of the month for the year 2020. It is necessary for the code to recognize and call the last Friday in the month of November every year, can anyone help, thank you.
Calendar lastday = Calendar.getInstance();
int month = lastday.get(Calendar.MONTH);
int dayOfMonth = lastday.get(Calendar.DAY_OF_MONTH);
if(month == Calendar.NOVEMBER && dayOfMonth == 27){
.....
}
your answer:
Calendar lastday = Calendar.getInstance();
int month = lastday.get(Calendar.MONTH);
int dayOfMonth = lastday.get(Calendar.DAY_OF_MONTH);
int day = lastday.get(Calendar.DAY_OF_WEEK);
if(month == Calendar.NOVEMBER && dayOfMonth >= 24 && day == Calendar.FRIDAY){
.....
}
You can use following solution. By changing calendar.set(Calendar.MONTH, Calendar.NOVEMBER), it should be usable for any month:
public int getLastFridayOfNovember() {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.MONTH, Calendar.NOVEMBER);
int totalDaysInMonth = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
calendar.set(Calendar.DAY_OF_MONTH, totalDaysInMonth);
int daysToRollBack = (calendar.get(Calendar.DAY_OF_WEEK) + 1) % 7;
return totalDaysInMonth - daysToRollBack;
}
Usage is simple:
...
int lastDayOfNovember = getLastFridayOfNovember();
If you use Kotlin, it can be extension function as well:
fun Calendar.getLastFridayOfMonth(): Int {
val totalDaysInMonth = getActualMaximum(Calendar.DAY_OF_MONTH)
this[Calendar.DAY_OF_MONTH] = totalDaysInMonth
val daysToRollBack = (this[Calendar.DAY_OF_WEEK] + 1) % 7
return totalDaysInMonth - daysToRollBack
}
Usage:
val calendar = Calendar.getInstance()
// set month
calendar.set(Calendar.MONTH, Calendar.NOVEMBER);
// get last Friday of given month
val lastFridayOfNovember = calendar.getLastFridayOfMonth()
java.time either through desugaring or through ThreeTenABP
Always consider using java.time, the modern Java date and time API, for your date work. And even more so for queries that are a bit more complex like yours here.
LocalDate today = LocalDate.now(ZoneId.systemDefault());
boolean isLastFridayOfNovember = today.getMonth().equals(Month.NOVEMBER)
&& today.equals(today.with(TemporalAdjusters.lastInMonth(DayOfWeek.FRIDAY)));
System.out.println("Is it the last Friday in November? " + isLastFridayOfNovember);
Output when I ran today (Thursday November 12):
Is it the last Friday in November? false
The expression today.with(TemporalAdjusters.lastInMonth(DayOfWeek.FRIDAY)) calculates the last Friday of the current month. If today is equal to the calculated date and we are in November, then we’re on the last Friday of November.
To calculate the last Friday in November for a given year:
int year = 2021;
LocalDate lastFridayInNovember = LocalDate.of(year, Month.NOVEMBER, 30)
.with(TemporalAdjusters.previousOrSame(DayOfWeek.FRIDAY));
System.out.println(lastFridayInNovember);
2021-11-26
Question: Doesn’t java.time require Android API level 26?
java.time works nicely on both 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) the modern API comes built-in.
In non-Android Java 6 and 7 get the ThreeTen Backport, the backport of the modern classes (ThreeTen for JSR 310; see the links at the bottom).
On older Android either use desugaring or the Android edition of ThreeTen Backport. It’s called ThreeTenABP. In the latter case make sure you import the date and time classes from org.threeten.bp with subpackages.
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.time to Java 6 and 7 (ThreeTen for JSR-310).
Java 8+ APIs available through desugaring
ThreeTenABP, Android edition of ThreeTen Backport
Question: How to use ThreeTenABP in Android Project, with a very thorough explanation.

Display time interval in minutes using joda Date time to display in Calendar

I want to display list of time interval with 15 minutes or 30 minutes like
like
1:00
1:15
1:30
1:45
or
1:00
1:30
2:00
2:30
below code is using Joda Date time library and it's showing time with interval of hours . I simply want to display time with interval of 15 or 30 minutes .
val hourDateTime = DateTime().withDate(2000, 1, 1).withTime(0, 0, 0, 0)
for (i in 1..23) {
val formattedHours = Formatter.getHoursWithMinutes(context!!, hourDateTime.withHourOfDay(i))
}
Formatter.kt
fun getHoursWithMinutes(context: Context, dateTime: DateTime) = dateTime.toString("h:mm a")
Instead of showing date(s) like 1:00 ,2:00 ,3:00 ,4:00 display with interval of 15 or 30 minutes
Currently working View which is working using Simple Calendar
I have tried another approach written below but this time time interval changes but hours remain same like
12:00 -> 12:30 -> 12:00 -> 12:30
val hourDateTime = DateTime().withDate(2000, 1, 1).withTime(0, 0, 0, 0)
var interval = 30
for (i in 1..23) {
if(i == 1 ) interval = 0
val formattedHours = Formatter.getHoursWithMinutes(context!!, hourDateTime.withMinuteOfHour(interval) )
interval += 30
if(interval == 60) interval = 0
}
java.time and ThreeTenABP
I can’t write Kotlin. Please translate from my Java.
Duration interval = Duration.ofMinutes(15);
LocalTime time = LocalTime.of(1, 0);
for (int i = 0; i < 10; i++) {
System.out.println(time);
time = time.plus(interval);
}
Output:
01:00
01:15
01:30
01:45
02:00
02:15
02:30
02:45
03:00
03:15
Set the interval to Duration.ofMinutes(30) to get 01:00, 01:30, etc.
I am using java.time, the modern Java date and time API, through the backport, see below. java.time is the successor of Joda-Time. I am sure something very similar to the above is possible with Joda-Time too in case you are already using Joda-Time and don’t want to migrate to java.time just now.
Question: Doesn’t java.time require Android API level 26?
java.time works nicely on both 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) the modern API comes built-in.
In non-Android Java 6 and 7 get the ThreeTen Backport, the backport of the modern 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.
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.time to 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.

date and time not working in Alarm Manager

I'm having trouble working with the AlarmManager. I want to run AlarmManager using Calendar at a specific time.
But the calendar doesn't work and AlarmManager always runs regardless of the time taken from the calendar.
AlarmManager mAlarmManger = (AlarmManager) Objects.requireNonNull(activity).getSystemService(view.getContext().ALARM_SERVICE);
Intent intent = new Intent(activity, MyReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(activity, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.WEEK_OF_YEAR, Calendar.MONTH , Calendar.DAY_OF_MONTH, 11, 55, 0);
calendar.set(Calendar.AM_PM, Calendar.AM);
if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O){
mAlarmManger.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
}
else{
mAlarmManger.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
}
AlarmManager should run at 11:55 AM everyDay, but will run as soon as the app opens.
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 11);
calendar.set(Calendar.MINUTE, 30);
calendar.set(Calendar.SECOND, 0);
if (calendar.getTimeInMillis() > System.currentTimeMillis()) {
Intent intent = new Intent(MainActivity.this, AlarmReceiver.class);
pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager am = (AlarmManager) MainActivity.this.getSystemService(MainActivity.this.ALARM_SERVICE);
am.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 24 * 60 * 60 * 1000, pendingIntent); //Repeat every 24 h
}
Try this..
java.time and ThreeTenABP
To obtain your time in millseconds since the epoch for the triggerAtMillis argument for your alarm manager:
long triggerAtMillis = ZonedDateTime.now(ZoneId.systemDefault())
.with(LocalTime.of(11, 55))
.toInstant()
.toEpochMilli();
To have this code work also on Android versions before Oreo (version code O, API level 26), add ThreeTenABP to your Android project, see the link at the bottom. And then make sure you import org.threeten.bp.ZonedDateTime, org.threeten.bp.ZoneId and org.threeten.bp.LocalTime.
What went wrong in your code?
The Calendar class was always poorly designed and has a confusing interface. No wonder that you made this error. You’re far from the first and unfortunately not the last either. In the original question you tried:
calendar.set(Calendar.WEEK_OF_YEAR, Calendar.MONTH , Calendar.DAY_OF_MONTH, 11, 55, 0);
In my time zone this sets the calendar date to Mon Mar 05 11:55:00 CET 3. That’s 2016 years and some months ago. So the alarm manager did the correct thing when running as soon as your app was opened. Could it be that you passed year 3, month 3 and day of month 5 to the method? Almost! The Calendar interface is working with fields that can be set independently: an era field, a year field, a month field, etc. Since this was designed before enums in Java, each field has a number, and of course a named constant for that number. The month field, for example, is field 2, so when you pass Calendar.MONTH for month, you are passing the value 2. So how come we get March? This is another confusing trait of Calendar, months are numbered from 0 for January through 11 for December, so 2 means March. The week of year field is field 3 and the day of month field is field 5. This explains the date you got.
Question: Doesn’t java.time require Android API level 26?
java.time works nicely on both 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) the modern API comes built-in.
In non-Android Java 6 and 7 get the ThreeTen Backport, the backport of the modern 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.
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.time to 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.

Get unix timestamp exactly 3 years from now

Using Android and Java 8, how can I get unix timestamps back in time?
E.g.
Exactly 3 years back from now
Exactly 2 months back from now
Exactly 1 day back from now
etc
I know I can get current timestamp using System.currentTimeMillis() / 1000L (you could also use Instant.now().getEpochSecond() from the new java.time, but this requires Android API > 25). Now I need to get offset and substract it. I could use TimeUnit.Days.toSeconds(), but if I want to substract years, it does not have YEAR unit and I don't want to mess with leap years myself.
Is there a simple way to do this?
Try this for getting timestamp using Calender....
For After 2 month.
Calendar date= Calendar.getInstance();
date.add(Calendar.MONTH, 2);//instead of 2 use -2 value in your case
date.getTimeInMillis();
For after one day.
Calendar date= Calendar.getInstance();
date.add(Calendar.DAY_OF_MONTH, 1);//instead of 1 use -1 value in your case
date.getTimeInMillis();
For after 3 years.
Calendar date= Calendar.getInstance();
date.add(Calendar.YEAR, 3);//instead of 3 use -3 value in your case
date.getTimeInMillis();
Note:- Use Negative value for back dates.
Hope it solve your problems.
java.time and ThreeTenABP
long threeYearsAgo = OffsetDateTime.now(ZoneOffset.UTC)
.minusYears(3)
.toEpochSecond();
System.out.println("Three years ago: "
+ NumberFormat.getIntegerInstance().format(threeYearsAgo));
When I ran this just now on my computer I got this output:
Three years ago: 1,446,737,905
I am not completely sure what you get if today happens to be February 29 in a leap year; probably the same time of day on February 28 three years ago. If you need to be sure, check the documentation or try it out.
For months or days ago use the minusMonths or minusDays method of OffsetDateTime.
the new java.time … requires Android API > 25
Not really: java.time has been backported.
In Java 8 and later and on newer Android devices (from API level 26) 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.
Links
Oracle tutorial: Date Time explaining how to use java.time.
OffsetDateTime.minusYears documentation
Java Specification Request (JSR) 310, where java.time was first described.
ThreeTen Backport project, the backport of java.time to 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.
long now = System.currentTimeMillis() - 1000;
setMaxDate(now+(1000*60*60*24*3) // 3 days from now
public void showDatedialog() {
DatePickerDialog dpd = new DatePickerDialog(DeliveryProduct.this,
new DatePickerDialog.OnDateSetListener() {
#Override
public void onDateSet(DatePicker view, int year, int month, int day) {
c.set(year, month, day);
String date = new SimpleDateFormat("yyyy-MM-dd").format(c.getTime());
edDate.setText(date);
mYear = c.get(Calendar.YEAR);
mMonth = c.get(Calendar.MONTH);
mDay = c.get(Calendar.DAY_OF_MONTH);
}
}, mYear, mMonth, mDay);
dpd.getDatePicker().setMinDate(System.currentTimeMillis() - 1000);
long now = System.currentTimeMillis() - 1000;
//dpd.getDatePicker().setMaxDate(now+(1000*60*60*24*3)); //for 3 days from now
Calendar d = Calendar.getInstance();
d.add(Calendar.MONTH, 1);
// dpd.getDatePicker().setMaxDate(d.getTimeInMillis());
dpd.show();
}
Getting unix timestamp one year ago from current time.
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.YEAR, -1);
long unixTimestamp = calendar.getTime().getTime() / 1000;
For month...
calendar.add(Calendar.MONTH, -1);

Android : how can I add 5 Times in a variable and get total seconds of them

like i have 5 Times
1. 05:12:02
2. 19:12:52
3. 40:12:14
4. 56:54:10
5. 41:12:12
-----------
Total Seconds : 0#####..`
-----------
i want like this, how can i , please help me .
can I use this? :
public String addTime(int hour, int minute, int minutesToAdd) {
Calendar calendar = new GregorianCalendar(1990, 1, 1, hour, minute);
calendar.add(Calendar.MINUTE, minutesToAdd);
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
String date = sdf.format(calendar.getTime());
return date;
}
Use the Duration class from java.time (the modern Java date and time API):
String[] times = {
"05:12:02",
"19:12:52",
"40:12:14",
"56:54:10",
"41:12:12"
};
Duration timeSum = Duration.ZERO;
for (String time : times) {
// reformat to ISO 8601
time = time.replaceFirst("(\\d{2}):(\\d{2}):(\\d{2})", "PT$1H$2M$3S");
// add
timeSum = timeSum.plus(Duration.parse(time));
}
System.out.println("Total seconds: " + timeSum.getSeconds());
Output:
Total seconds: 585810
The Duration class cannot directly parse your time strings. It parses ISO 8601 standard format, so I use a regular expression for converting 05:12:02 to PT05H12M02S. Then I feed this into Duration.parse. You may read the ISO 8601 string as “a period of time of 05 hours 12 minutes 02 seconds”.
Classes meant for dates and times — Date, Calendar, LocalTime, etc. — are ill suited for amounts of time. Date and Calendar are furthermore long outdated and poorly designed, so don’t try those. While it wouldn’t be impossible to get through, there are some pitfalls, and even if you succeed, it will be hard to read the code and convince oneself that it is correct.
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). The code above was developed and run with org.threeten.bp.Duration from the backport.
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.
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.time to 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.
Wikipedia article: ISO 8601
A easy way to do it, if the format is the one you have pointed, without have to worry in convert the Date is the following:
int totalSum = getSecondsFromDate("05:12:02") + getSecondsFromDate("19:12:52") + getSecondsFromDate("40:12:14") + getSecondsFromDate("56:54:10") + getSecondsFromDate("41:12:12");
private int getSecondsFromDate(String date){
//We split the date to have hours, minutes and seconds
String splitDate = date.split(":");
int hours = Integer.parseInt(splitDate[0]);
int minutes = Integer.parseInt(splitDate[1]);
int seconds = Integer.parseInt(splitDate[2]);
int totalSeconds = (hours*60*60) + (minutes*60) + seconds;
return totalSeconds;
}

Categories

Resources