I have a ListView that users will put comment in. When they hit "submit" attached to an EditText box, the new comment goes into a MySQL database along with the current time.
I'd like the comments to appear in the listview with dates similar to Youtube formatting. For example: "10 seconds ago", "1 day ago", "52 days ago".
Would I use the Calendar object, SimpleDateFormat, something else?
Also, how would I store the date in the datebase? I am assuming something easily convertible like the UNIX date stamp maybe. And then would it be in the ArrayAdapter where I dynamically change the date based on the current time?
You can use PrettyTime to achieve that.
For saving time, I usually save time in millis.
To get this you need to calculate the difference between your timestamp and current timestamp (keep them in milliseconds for simplicity). The result will be number of milliseconds "ago". Then use simple math like subtraction and division and you can get number of minutes, days, weeks and whatever-you-want.
EDIT: I use this:
public static final long MILLIS_PER_SECOND = 1000;
public static final long MILLIS_PER_MINUTE = (MILLIS_PER_SECOND * 60);
public static final long MILLIS_PER_HOUR = (MILLIS_PER_MINUTE * 60);
public static final long MILLIS_PER_DAY = (MILLIS_PER_HOUR * 24);
public static final long MILLIS_PER_WEEK = (MILLIS_PER_DAY * 7);
public static final long MILLIS_PER_MONTH = (MILLIS_PER_DAY * 30);
public static final long MILLIS_PER_YEAR = (MILLIS_PER_MONTH * 12);
Note that is is not 100% correct as I (intentionally, for simplicy) made false assumption month is always 30 days long, which also influences MILLIS_PER_YEAR. But I do not really care - it's not rocket science I use these for. But you may reduce the impact by setting MILLIS_PER_YEAR this way:
public static final long MILLIS_PER_YEAR = (MILLIS_PER_DAY * (7*31 + 4*30 + 28));
28 is for February, in this case you only be 1 day off on leaps years, instead of 5 days as in former version.
Try DateUtils.getRelativeTimeSpanString to format the date for display.
Related
Below is my code.
public class TestCalendar {
public static void main(String[] args){
int unique_id = Integer.parseInt("" + Calendar.HOUR + Calendar.MINUTE
+ Calendar.SECOND);
System.out.println(unique_id);
}
}
Calendar.HOUR is supposed to give me
public static final int HOUR Field number for get and set indicating the hour of the morning or
afternoon. HOUR is used for the 12-hour clock (0 - 11). Noon and midnight are represented by 0, not
by 12. E.g., at 10:04:15.250 PM the HOUR is 10.
It doesnt matter how many times I run this code, it always gives me the same unique_id. (101213) and my local time on my machine is 1:30pm. What am I doing wrong here?
Thanks.
Your code is just concatenating constants, that the Calendar defines to identify some of it's fields. To get values of these fields, call Calendar.get() and pass the constant identifier as an argument:
public class TestCalendar {
public static void main(String[] args){
Calendar c = Calendar.getInstance();
int unique_id = Integer.parseInt("" + c.get(Calendar.HOUR) + c.get(Calendar.MINUTE)
+ c.get(Calendar.SECOND));
System.out.println(unique_id);
}
}
The above would work, but the result will be far from unique ID.
To get an ID uniquely identifying a point in time (with the precision of milliseconds), consider Calendar.getTimeInMillis().
Calendar.HOUR, Calendar.MINUTE and Calendar.SECOND are public static int field of the Calendar class. Their value is
CALENDAR.HOUR: 10
CALENDAR.MINUTE: 12 and
CALENDAR.SECOND: 13.
Your String concatenation is just appending this values. To read from a Calendar you could so something similar to
calendar.get(Calendar.HOUR);
calendar.get(Calendar.MINUTE);
I am not sure what is requirement but if you want system time then may be you can use this "System.currentTimeMillis()"
Calendar.HOUR (or MINUTE, SECOND) is just an indicator that indicates which field we want to extract from the Calendar instance, not the value, i.e. we want to 'extract HOUR from the calendar object' like below:
Calendar c = Calendar.getInstance();
int hour = c.get(Calendar.HOUR_OF_DAY); // in 24-hours,
// or c.get(Calendar.HOUR) in 12-hours.
int minute = c.get(Calendar.MINUTE);
int second = c.get(Calendar.SECOND);
int weekday = c.get(Calendar.DAY_OF_WEEK);
int weekOfYear = c.get(Calendar.WEEK_OF_YEAR);
For those who are still having some problems with this, like I did, especially when you want to print multiple times you may need to to use new like follows:
System.out.println(""+new GregorianCalendar().get(Calendar.HOUR_OF_DAY)+":"+new GregorianCalendar().get(Calendar.MINUTE)+":"+new GregorianCalendar().get(Calendar.SECOND)+":"+new GregorianCalendar().get(Calendar.MILLISECOND));
Today is 18/12/2013.
I was testing this program where I wanted get another date by adding/substracting a number of milliseconds from System.currentMillis(). It works well when I shift the date in decembre but it doesn't work correctly for some similar values. For example the following code gives me 2013 12 20 as the result! I wonder, no I still wonder how it could be possible! or I'm making a mistake?
public class CreateDirFiles {
public static final String PLOG_DIR = "ProductLog";
private SimpleDateFormat dateFormatter = new SimpleDateFormat();
public CreateDirFiles() {
}
public void createDayDir(Date date){
dateFormatter.applyPattern("YYYY");
String year = dateFormatter.format(date);
dateFormatter.applyPattern("MM");
String month = dateFormatter.format(date);
dateFormatter.applyPattern("dd");
String day = dateFormatter.format(date);
System.out.printf("%s %s %s\n", year, month, day);
}
public static void main(String... args){
CreateDirFiles dfc = new CreateDirFiles();
dfc.createDayDir(new Date(System.currentTimeMillis() -
((long)( 48 * 24 * 3600 * 1000)) ));
}
}
This is the problem:
((long)( 48 * 24 * 3600 * 1000))
That's doing all the arithmetic in 32 bits, and then converting the (now truncated, as the result is too large for an int) result to a long. You want:
48L * 24 * 3600 * 1000
where the L suffix means that it'll use a long for the value 48.
However, you really don't want to do this at all - you want to use Joda Time which is a much nicer API for date/time work. You really don't want to have to mess around with the low level stuff at all.
LocalDate date = ...;
LocalDate twoDaysLater = date.minusDays(48);
If you really want to stick with the built-in API, then use Calendar. At the very least use the TimeUnit enum, which will allow:
long millisFor48Days = TimeUnit.DAYS.toMillis(48);
You also need to consider the time zone - while "today" may be the 18th of December for you, it isn't elsewhere in the world.
Please help me to write a method that returns number (int) of days from a provided day to the todays date.
So let's say, I am providing into a method an int 110515 (for May 15, 2011). It should return 9 (inclusive or exclusive is not important to me).
If you can use Joda, this is super simple:
Days d = Days.daysBetween(startDate, endDate);
int days = d.getDays();
Of course you could combine these.
int days = Days.daysBetween(startDate, endDate).getDays();
Joda objects can go back and forth between the JDK's date class pretty easily.
For the first part, make a DateFormatter then parse the string based on it, like this:
DateTimeFormatter fmt = DateTimeFormat.forPattern("yyyyMMdd");
DateTime dt = fmt.parseDateTime(strInputDateTime);
(After turning the int into a string of course.)
Should dates in the future include the current day? Meaning if today is May 24th 2011, should 110529 result in 4 or 5?
public static long numberOfDays(final long date) throws ParseException {
final Calendar compare = Calendar.getInstance();
compare.setTime(new SimpleDateFormat("yyMMdd").parse(String.valueOf(date)));
final int dstOffset = compare.get(Calendar.DST_OFFSET);
final long currentTimeMillis = System.currentTimeMillis();
final long compareTimeInMillis = compare.getTimeInMillis();
long difference = 0;
if (currentTimeMillis >= compareTimeInMillis) {
difference = currentTimeMillis - compareTimeInMillis - dstOffset;
} else {
difference = compareTimeInMillis - currentTimeMillis + dstOffset;
}
return difference / (24 * 60 * 60 * 1000);
}
Since this seems like a homework question I will help you out. You will want to use Calendar.getTimeInMillis. Then you will want to create a constant that is NUMBER_OF_MILLIS_IN_DAY . From there you subtract the initialDate from the currentDate (both time in millis) and divide by the constant.
Are there any Java libraries around for dealing with the win32 FILETIME/ time intervals ?
It's basically a 64 bit timestamp in 100ns intervals since January 1, 1601.
(For my particular needs, converting to/from java.util.Date or an appropriate joda time equivalent would do, although I'll need access to at least microsecond resolution - which neither seems to provide.)
If you are fine with millisecond resolution, this would work:
/** Difference between Filetime epoch and Unix epoch (in ms). */
private static final long FILETIME_EPOCH_DIFF = 11644473600000L;
/** One millisecond expressed in units of 100s of nanoseconds. */
private static final long FILETIME_ONE_MILLISECOND = 10 * 1000;
public static long filetimeToMillis(final long filetime) {
return (filetime / FILETIME_ONE_MILLISECOND) - FILETIME_EPOCH_DIFF;
}
public static long millisToFiletime(final long millis) {
return (millis + FILETIME_EPOCH_DIFF) * FILETIME_ONE_MILLISECOND;
}
At this point, converting from ms to a Date object is quite straightforward.
Here's a Java 8+ java.time based solution that keeps 100-nanosecond precision:
public static final Instant ZERO = Instant.parse("1601-01-01T00:00:00Z");
public static long fromInstant(Instant instant) {
Duration duration = Duration.between(ZERO, instant);
return duration.getSeconds() * 10_000_000 + duration.getNano() / 100;
}
public static Instant toInstant(long fileTime) {
Duration duration = Duration.of(fileTime / 10, ChronoUnit.MICROS).plus(fileTime % 10 * 100, ChronoUnit.NANOS);
return ZERO.plus(duration);
}
Last time I solved this using JNI... (Although not on Windows, this was unix)
That is, a piece of C++ code that called the native OS functions, and then called that code using Java Native Interface.
A bit clunky, but it was the only way I could find (Also needed the i-node).
EDIT: Assuming the values are already obtained from some other source, Date4J can handle seconds with 9 decimals, but it is not as feature rich as Joda.
Since GWT does not provide the GregorianCalendar class, how to do calendar operations on the client?
I have a Date a and I want the Date, which is n days after a.
Examples:
a (2000-01-01) + n (1) -> 2000-01-02
a (2000-01-01) + n (31) -> 2000-02-01
Updated answer for GWT 2.1
final Date dueDate = new Date();
CalendarUtil.addDaysToDate(dueDate, 21);
Edit: the fully qualified name of this class is com.google.gwt.user.datepicker.client.CalendarUtil.
The answer that Google seems to use (currently), is:
#SuppressWarnings("deprecation") // GWT requires Date
public static void addDaysToDate(Date date, int days) {
date.setDate(date.getDate() + days);
}
This is from the class com.google.gwt.user.datepicker.client.CalendarUtil, which is used by com.google.gwt.user.datepicker.client.DatePicker. I imagine, that there will be problems involved, when doing calculations in different timezones.
Lots of people have already voted for some kind of Joda time for GWT: http://code.google.com/p/google-web-toolkit/issues/detail?id=603 . The currently last comment states, that there's a new fork of goda time, maybe we should really check it out.
private static final long MILLISECONDS_IN_SECOND = 1000l;
private static final long SECONDS_IN_MINUTE = 60l;
private static final long MINUTES_IN_HOUR = 60l;
private static final long HOURS_IN_DAY = 24l;
private static final long MILLISECONDS_IN_DAY = MILLISECONDS_IN_SECOND *
SECONDS_IN_MINUTE *
MINUTES_IN_HOUR *
HOURS_IN_DAY;
public Date addDays (Date date, days)
{
return new Date (date.getTime () + (days * MILLISECONDS_IN_DAY));
}
this will work with leap years but will eventually stray by milliseconds on milleniums when we add or drop leap seconds.
I've created a rough implementation that emulates TimeZone, Calendar, and Locale. Feel free to try it out here:
http://code.google.com/p/gwt-calendar-class/downloads/list