我想制作日历视图以支持触摸互动。 所以我想构建新的自定义日历视图。 我试图在视图偏移和实际日期值之间建立映射函数。
这是我的想法: 如果我可以计算自基准日期以来的周数(在我的情况下,1989-12-31), 很容易知道偏移量。 HEIGHT_FOR_WEEK * NUM_OF_WEEK是非常简单的计算 知道确切的偏移量。
我的问题是: 首先,我从基准日期获得毫秒值。我将毫秒设置为 另一个日历对象。我期望该对象的日期相同。但实际上 这是不同的日期。
mBaseDateInMillis = mBaseDate.getTimeInMillis();
mAnotherDate.setTimeInMillis(mBaseDateInMillis);
/* I expect mBaseDate == mAnotherDate.
* but it was different.
*/
这是我的代码:
public class CalendarCoordinate {
public static final long ONEWEEK_IN_MILLISECONDS = 60 * 60 * 24 * 7 * 1000;
public Calendar mBaseDate = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
public long mBaseDateInMillis = 0;
public Calendar mDate = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
public int mWeekHeight = 30;
/**
* CTOR
*/
public CalendarCoordinate() {
/* Base date is 1989-12-31 0, 0, 0
* It was Sunday and offset 0 will be mapped onto this day.
*/
mBaseDate.set(Calendar.MILLISECOND, 0);
mBaseDate.set(1989, 12, 31, 0, 0, 0);
mBaseDateInMillis = mBaseDate.getTimeInMillis();
Log.v(TAG, "BaseDate:" + mBaseDate.toString());
}
/**
* Compute DATE from Y-Offset
* @param yOffset
* @return
*/
public Calendar dateFromYOffset(int yOffset) {
long nthWeeks = yOffset / mWeekHeight;
long millsSinceBaseDate = nthWeeks * ONEWEEK_IN_MILLISECONDS;
mDate.clear();
mDate.set(Calendar.MILLISECOND, 0);
mDate.setTimeInMillis(mBaseDateInMillis + millsSinceBaseDate);
/* We SHOULD call to update mDate internal data structure.
* Java is really strange for this thing
**/
mDate.getTimeInMillis();
return mDate;
}
/**
* Compute Y-Offset from DATE
* @param date
* @return
*/
public long yOffsetFromDate(Calendar cal) {
long mills = cal.getTimeInMillis();
long nthWeeks = (mills - mBaseDateInMillis)/ONEWEEK_IN_MILLISECONDS;
return nthWeeks * mWeekHeight;
}
}
任何人都可以帮助我吗?我不是一个优秀的Java程序员。
答案 0 :(得分:5)
这句话让我感到困惑:
/* I expect mBaseDate == mAnotherDate.
* but it was different.
*/
您是否真的试图通过比较来检查相等性: if(mBaseDate == mAnotherDate){System.out.println(“它们是相同的”); }
如果是这样,您的问题是您误解了“==”运算符在Java中的工作原理。它比较引用,而不是比较底层对象数据,因为它们是不同的对象(具有相同的值),它们总是为假。有关详细信息,请参阅Java Notes on comparison operators。
此外,这些线条对我来说真的很可疑:
/* We SHOULD call to update mDate internal data structure.
* Java is really strange for this thing
**/
mDate.getTimeInMillis();
如果Android有一个要求你这样做的bug,我真的会感到惊讶,但我想任何事都有可能。没有这个电话,你有什么问题?
答案 1 :(得分:3)
这是因为您需要使用“equals”方法来比较不同的对象。使用运算符“==”将告诉您对象是否相同(它们是否位于完全相同的内存位置),而“等于”比较函数将告诉您这两个对象是否在逻辑上等效。
答案 2 :(得分:0)
long weeks = ChronoUnit.WEEKS.between ( LocalDate.of ( 1989 , 12 , 31 ) , LocalDate.of ( 1990 , 1 , 14 ) ); // Results: 2
不要在count-since-epoch(例如毫秒)中工作。令人困惑,掩盖错误,并忽略时区等问题。
让一个好的日期时间库在这些计算中做繁重的工作。
您正在使用麻烦的旧日期时间类,例如java.util.Calendar
。这些设计糟糕的类已被Java 8及更高版本中内置的java.time框架所取代。见Oracle Tutorial。许多java.time功能已经被反向移植到Java 6& ThreeTen-Backport中的7,并在ThreeTenABP中进一步适应Android。
ChronoUnit
ChronoUnit
课程计算一对LocalDate
(仅限日期,无时间和时区)值之间的经过时间,例如整周数。
LocalDate start = LocalDate.of ( 2016 , 1 , 1 );
LocalDate stop = start.plusDays ( 17 ); // Ex: 13 days = 1 week. 14 days = 2 weeks.
long weeks = ChronoUnit.WEEKS.between ( start , stop );
转储到控制台。
System.out.println ( "start: " + start + " | stop: " + stop + " | weeks: " + weeks );
开始:2016-01-01 |停止:2016-01-18 |周:2
如果您想要1989-12-31
后的几周,请将其用作上面显示的start
对象。
LocalDate start = LocalDate.of( 1989 , 12 , 31 );
但我注意到你的基准日期是一年中的最后一天。提示:时间跨度通常最好使用半开放方法处理,其中开头是包含,而结尾是独占。所以你可能想要使用1990-01-01
作为你的基准日期(我不知道你的业务逻辑,所以我只想猜测一下。)
所以你前两周就是这个(1日至15日):
long firstTwoWeeks = ChronoUnit.WEEKS.between ( LocalDate.of ( 1990 , 1 , 1 ) , LocalDate.of ( 1990 , 1 , 15 ) );
...而不是这个(31-14):
long firstTwoWeeks = ChronoUnit.WEEKS.between ( LocalDate.of ( 1989 , 12 , 31 ) , LocalDate.of ( 1990 , 1 , 14 ) );