Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trial
Josh Gold
12,207 PointsHow to list the days of the week in Stormy for extended forecast
I have built the 7 day forecast activity for the Stormy Android app. Unfortunately the extended forecast says "Monday" next to each day of the 7 day forecast.
I uploaded a screen capture here: http://imgur.com/QS8CpY1
Anybody have some hints or ideas on how to list the next 7 days of the week, starting with today. This app uses ListView layout for the extended forecast.
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
public class DayAdapter extends BaseAdapter {
private Context mContext;
private Day[] mDays;
public DayAdapter(Context context, Day[] days) {
mContext = context;
mDays = days;
}
@Override
public int getCount() {
return mDays.length;
}
@Override
public Object getItem(int position) {
return mDays[position];
}
@Override
public long getItemId(int position) {
return 0; // we aren't going to use this. Tag items for easy reference
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
// brand new
convertView = LayoutInflater.from(mContext).inflate(R.layout.daily_list_item, null);
holder = new ViewHolder();
// holder.iconImageView = (ImageView) convertView.findViewById(R.id.iconImageView);
holder.temperatureLabel = (TextView) convertView.findViewById(R.id.temperatureLabel);
holder.dayNameLabel = (TextView) convertView.findViewById(R.id.dayNameLabel);
holder.lowTempLabel = (TextView) convertView.findViewById(R.id.lowTempLabel);
convertView.setTag(holder);
}
else {
holder = (ViewHolder) convertView.getTag();
}
Day day = mDays[position];
// holder.iconImageView.setImageResource(day.getIconId());
holder.temperatureLabel.setText(day.getTemperatureMax() + "");
holder.lowTempLabel.setText(day.getTemperatureMin() + "");
holder.dayNameLabel.setText(day.getDayOfTheWeek());
return convertView;
}
private static class ViewHolder {
ImageView iconImageView; // public by default
TextView temperatureLabel;
TextView lowTempLabel;
TextView dayNameLabel;
}
}
package com.joshbgold.WeatherBuddy;
import android.os.Parcel;
import android.os.Parcelable;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
public class Day implements Parcelable{
private long mTime;
private String mSummary;
private String mIcon;
private String mTimeZone;
private double mTemperatureMax;
private double mTemperatureMin;
private long mSunrise;
private long mSunset;
private double mMoonPhase;
public long getTime() {
return mTime;
}
public void setTime(long time) {
mTime = time;
}
public String getSummary() {
return mSummary;
}
public void setSummary(String summary) {
mSummary = summary;
}
public int getTemperatureMax() {
return (int)Math.round(mTemperatureMax);
}
public void setTemperatureMax(double temperatureMax) {
mTemperatureMax = temperatureMax;
}
public double getTemperatureMin() {
return (int)Math.round(mTemperatureMin);
}
public void setTemperatureMin(double temperatureMin) {
mTemperatureMin = temperatureMin;
}
public String getIcon() {
return mIcon;
}
public void setIcon(String icon) {
mIcon = icon;
}
public String getTimeZone() {
return mTimeZone;
}
public void setTimeZone(String timeZone) {
mTimeZone = timeZone;
}
public int getIconId() {
return Forecast.getIconId(mIcon);
}
public String getDayOfTheWeek() {
SimpleDateFormat formatter = new SimpleDateFormat("EEEE");
formatter.setTimeZone(TimeZone.getTimeZone(mTimeZone));
Date date = new Date();
String dayOfTheWeek = formatter.format(date);
return dayOfTheWeek;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeLong(mTime);
dest.writeString(mSummary);
dest.writeDouble(mTemperatureMax);
dest.writeDouble(mTemperatureMin);
dest.writeString(mIcon);
dest.writeString(mTimeZone);
}
private Day(Parcel in) {
mTime = in.readLong();
mSummary = in.readString();
mTemperatureMax = in.readDouble();
mTemperatureMin = in.readDouble();
mIcon = in.readString();
mTimeZone = in.readString();
}
public Day() { }
public static final Creator<Day> CREATOR = new Creator<Day>() {
@Override
public Day createFromParcel(Parcel source) {
return new Day(source);
}
@Override
public Day[] newArray(int size) {
return new Day[size];
}
};
public String getMoonPhaseDescription() {
String phaseDescription;
if (mMoonPhase == 0) {
phaseDescription = "new moon";
} else if (mMoonPhase > 0 && mMoonPhase < 0.25) {
phaseDescription = "waxing crescent";
} else if (mMoonPhase == 0.25) {
phaseDescription = "first quarter";
} else if (mMoonPhase > 0.25 && mMoonPhase < 0.5) {
phaseDescription = "waxing gibbous";
} else if (mMoonPhase == 0.5) {
phaseDescription = "full moon";
} else if (mMoonPhase > 0.5 && mMoonPhase < 0.75) {
phaseDescription = "waning gibbous";
} else if (mMoonPhase == 0.75) {
phaseDescription = "last quarter";
} else if (mMoonPhase > 0.75 && mMoonPhase < 1) {
phaseDescription = "waning crescent";
} else phaseDescription = "--";
return phaseDescription;
}
public void setMoonPhase(double moonPhase) {
mMoonPhase = moonPhase;
}
public long getSunrise() {
return mSunrise;
}
public String getFormattedSunriseTime(){ //converts Unix time we receive from API, to human readable time
SimpleDateFormat formatter = new SimpleDateFormat("h:mm");
formatter.setTimeZone(TimeZone.getTimeZone(getTimeZone()));
Date dateTime = new Date(getSunrise() * 1000);
return formatter.format(dateTime);
}
public void setSunrise(long sunrise) {
mSunrise = sunrise;
}
public long getSunset() {
return mSunset;
}
public String getFormattedSunsetTime(){ //converts Unix time we receive from API, to human readable time
SimpleDateFormat formatter = new SimpleDateFormat("h:mm");
formatter.setTimeZone(TimeZone.getTimeZone(getTimeZone()));
Date dateTime = new Date(getSunset() * 1000);
return formatter.format(dateTime);
}
public void setSunset(long sunset) {
mSunset = sunset;
}
}
Seth Kroger
56,416 PointsIs the time you get from forecast.io in seconds or milliseconds? If the former, you'll need to multiply by 1000.
Josh Gold
12,207 PointsForecast.io API uses seconds for the time. So yes I will need to multiply by 1000 to get milliseconds. Still getting a result in which every returned value is shown as "Wednesday".
When I am calling day.getDayOfTheWeek, the object day should have all the data needed, included the time. In fact the min and max temperatures are returned correctly. But I am missing something on using the time provided by the day object to return the day of the week.
I am going to try to add the icon for the forecast as well to see if that has similar problems or not.
Josh Gold
12,207 PointsI am going to set a breakpoint immediately after the extended forecast is retrieved, and try to look at the contents of the day object returned from forecast.io to see all the values.
Josh Gold
12,207 PointsLooks like the high temp and low temp are the only variables that are getting values from forecast.io for the extended forecast: http://imgur.com/VV0o3qy
I don't know why as yet.
Josh Gold
12,207 PointsSeth, it was a team effort!
3 Answers
Seth Kroger
56,416 PointsIn getDayOfTheWeek() you are using the default constructor for Date which returns the date now, instead of passing it the time for the date you want to convert.
Josh Gold
12,207 PointsCan you elaborate a little more on that? Are you saying that the getDayOfTheWeek method in Day.java needs to allow passing in a date, so that it can return a day name?
Should the new code in DayAdapter.java look like this?
holder.dayNameLabel.setText(day.getDayOfTheWeek(day));
Seth Kroger
56,416 Points public String getDayOfTheWeek() {
SimpleDateFormat formatter = new SimpleDateFormat("EEEE");
formatter.setTimeZone(TimeZone.getTimeZone(mTimeZone));
Date date = new Date(); // <--- I'm talking about this. It creates a Date for "now",
// not a Date associated with the Day object this method is called on
String dayOfTheWeek = formatter.format(date);
return dayOfTheWeek;
}
Josh Gold
12,207 PointsOk I am passing in the day to the getDayOfTheWeek method, but I don't think the day variable is the right format for the format method to operate on, hence I get a IllegalArgument Exception when it tries to format(day)
How might I get this method to operate on the day variable to return the day of the week?
public String getDayOfTheWeek(Day day) {
SimpleDateFormat formatter = new SimpleDateFormat("EEEE");
formatter.setTimeZone(TimeZone.getTimeZone(mTimeZone));
//Date date = new Date();
String dayOfTheWeek = formatter.format(day);
return dayOfTheWeek;
}
Seth Kroger
56,416 PointsGetters usually aren't supposed to have arguments because they are already associated with the object they're called on. Calling on it as day.getDayOfTheWeek(day) is redundant because it already has access to every field in day. It can and should be called as just day.getDayOfTheWeek().
Notice that I'm calling it a "getter" even though it's a bit more complicated than just returning the value of a member variable. That's irrelevant outside the class because, if you'll recall, classes are supposed to act like black boxes, and any get..() should return the relevant information about the object regardless of how it obtains it. The flip side is inside the class, what you return should be related to the object's member variables. And, you're missing a key one: when the Day forecast is for.
(As a hint, take a look the difference between new Date() and new Date(long) http://developer.android.com/reference/java/util/Date.html#Date%28%29 )
Josh Gold
12,207 PointsSeth, you identified one of the problems correctly... I was using the the default constructor for Date, which returns the date for now, instead of passing in the time for the date I need to convert.
The 2nd problem: In main activity, in getDailyForecast method, I was not retrieving the time from Forecast.io. I added the following line: <br>
day.setTime(jsonDay.getLong("time"));
I also retrieved all the other data that I didn't know I was missing!
Seth Kroger
56,416 PointsFantastic! I always hate it when fixing one problem uncovers another it was hiding. You did a great job tracking down the second.
Seth Kroger
56,416 PointsSimpleDateFormat.format() is supposed to work with Date objects. Try this instead.
public String getDayOfTheWeek() {
SimpleDateFormat formatter = new SimpleDateFormat("EEEE");
formatter.setTimeZone(TimeZone.getTimeZone(mTimezone));
Date dateTime = new Date(mTime * 1000);
return formatter.format(dateTime);
}
Josh Gold
12,207 PointsI used your code exactly, except my time zone variable is called mTimeZone (different capitalization).
Still returns "Wednesday" for the next seven days. I am going to sleep on this one.
Josh Gold
12,207 PointsJosh Gold
12,207 PointsOk, so I probably need to use Date(long). I tried this:
The method getTime does indeed return a long value. Interesting result though. Now every day in the ListView layout shows "Wednesday". I guess I don't understand how inside this method I am supposed to access the day object.