I have a long value that represents the time of day in milliseconds since midnight that day. i.e. 00:00:01 would be 1000.
I want to convert this to a long timestamp since the epoch - using the current System's day, month, year. What's the best way to do this?
final Calendar instance = Calendar.getInstance();
instance.set(Calendar.HOUR, 0);
instance.set(Calendar.MINUTE, 0);
instance.set(Calendar.SECOND, 0);
instance.set(Calendar.MILLISECOND, 0);
long result = instance.getTimeInMillis() + yourTime;
Also note that Calendar#getInstance does the following:
Calendar cal = createCalendar(TimeZone.getDefaultRef(), Locale.getDefault());
The resulting time will change according to the default set TimeZone (and yes it can change !). See this post: java Timezone setDefault effects
Try this:
Date date = new Date(your_long_value);
Related
I get a string in the format yyyy-MM-dd HH:mm which represents a Date and Time in UTC.
Next step is to put this into a Calendar (with TimeZone UTC).
In addition need to also create a separate Calendar which has converted the UTC to "Europe/London" timeZone (GMT/BST).
After that I need to be able to detect if the "Europe/London" calendar has a DST (Day Light Savings Offset).
The code below will show you how far I have got and it runs ok on a UK based computer whose default System Timezone is GMT. However when I run it on a pc whose timezone is UTC it fails. It seems to not be able to tell me if there is an DST_offset (its always zero).
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
cal.set(Calendar.YEAR, 2016);
cal.set(Calendar.MONTH, 1);
cal.set(Calendar.DAY_OF_MONTH, 27);
cal.set(Calendar.HOUR_OF_DAY, 23);
cal.set(Calendar.MINUTE, 35);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
//This is required as Java Date JAN starts at 0.
int MonthCon = cal.get(Calendar.MONTH)-1;
cal.set(Calendar.MONTH, MonthCon);
Date d = cal.getTime();
SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ssz");
f.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println("UTC: " + f.format(d));
f.setTimeZone(TimeZone.getTimeZone("Europe/London"));
System.out.println("BST: " + f.format(d));
//Creates a BST calendar of the same UTC time
String dateStrBST = f.format(d);
SimpleDateFormat curFormater = new SimpleDateFormat("yyyy-MM-dd HH:mm:ssz");
curFormater.setTimeZone(TimeZone.getTimeZone("Europe/London"));
Date dateObjBST = curFormater.parse(dateStrBST);
System.out.println("BSTNewDate: " + f.format(dateObjBST));
Calendar calBST = Calendar.getInstance(TimeZone.getTimeZone("BST"));
calBST.setTime(dateObjBST);
System.out.println("Current TimeZone is : " + calBST.getTimeZone());
int offset = calBST.get(Calendar.DST_OFFSET);
System.out.println("Day Light Savings: "+offset);
System.out.println("Transition Day: "+isDSTTransitionDay(cal.get(Calendar.YEAR),cal.get(Calendar.MONTH),cal.get(Calendar.DAY_OF_MONTH))+" Transition Type: "+DSTtransitionType(cal.get(Calendar.YEAR),cal.get(Calendar.MONTH),cal.get(Calendar.DAY_OF_MONTH)));
Unfortunately I need to be able to detect if any particular day is a transition day, that is to say a day that changes from DST on/off or off/on. Again this works on the local computer but not on the UTC timezone one.
private static boolean isDSTTransitionDay(int year, int month, int day) throws ParseException
{
Calendar calStartofDay = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
calStartofDay.set(Calendar.YEAR, year);
calStartofDay.set(Calendar.MONTH, month);
calStartofDay.set(Calendar.DAY_OF_MONTH, day);
calStartofDay.set(Calendar.HOUR_OF_DAY, 00);
calStartofDay.set(Calendar.MINUTE, 0);
calStartofDay.set(Calendar.SECOND, 1);
Date dStartofDay = calStartofDay.getTime();
SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ssz");
f.setTimeZone(TimeZone.getTimeZone("Europe/London"));
String dateStrUTCtoBST = f.format(dStartofDay);
SimpleDateFormat curFormater = new SimpleDateFormat("yyyy-MM-dd HH:mm:ssz");
curFormater.setTimeZone(TimeZone.getTimeZone("Europe/London"));
Date dateObjBST = curFormater.parse(dateStrUTCtoBST);
Calendar calBST = Calendar.getInstance();
calBST.setTime(dateObjBST);
int offsetStart = calBST.get(Calendar.DST_OFFSET);
calBST.add(Calendar.HOUR_OF_DAY, 23);
int offsetEnd = calBST.get(Calendar.DST_OFFSET);
//System.out.println("Start: "+offsetStart+" End: "+offsetEnd);
if (offsetEnd == offsetStart)
{
return false;
}else
{
//if(offsetStart<offsetEnd) {System.out.println("Transition to BST");}else{System.out.println("Transition to UTC/GMT");};
return true;
}
}
So on the UTC computer it fails miserably as it always puts Calendar.DST_OFFSET at zero. I have clearly misunderstood something along the way so any help/clarity would be good.
I pretty much have to keep Calendars as the rest of the code uses it but I realise the Java8 has many more fancy ways to do things.
Please allow me to be honest, I tried to read your code and didn’t really understand your way of trying to obtain what you want. If you can use Java 8, I recommend switching to using the Java 8 date and time classes. With these your job isn’t very complicated. For the demonstration I have chosen last October 30, the date when Britain (and EU) changed back from summer time (daylight saving time) to standard time.
String originalDate = "2016-10-30 23:35";
LocalDateTime localTime = LocalDateTime.parse(originalDate, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"));
ZonedDateTime utcTime = localTime.atZone(ZoneOffset.UTC);
ZonedDateTime bstTime = utcTime.withZoneSameInstant(ZoneId.of("Europe/London"));
// the summer time offset is how many milliseconds?
long dstOffset = ChronoUnit.MILLIS.between(utcTime.toLocalDateTime(), bstTime.toLocalDateTime());
System.out.println(dstOffset); // prints 0
// try the same at start of day (midnight)
utcTime = utcTime.toLocalDate().atStartOfDay(ZoneOffset.UTC);
bstTime = utcTime.withZoneSameInstant(ZoneId.of("Europe/London"));
dstOffset = ChronoUnit.MILLIS.between(utcTime.toLocalDateTime(), bstTime.toLocalDateTime());
System.out.println(dstOffset); // prints 3600000
// and next midnight
utcTime = utcTime.plusDays(1);
bstTime = utcTime.withZoneSameInstant(ZoneId.of("Europe/London"));
dstOffset = ChronoUnit.MILLIS.between(utcTime.toLocalDateTime(), bstTime.toLocalDateTime());
System.out.println(dstOffset); // prints 0
You are using
Calendar calBST = Calendar.getInstance();
That sets calBST to the computer's timezone (on the UTC computer, it will be UTC).
calBST.setTime(dateObjBST); sets the time, not the timezone.
Try using getInstance(TimeZone zone) there also.
In any case, I would replace your code like this:
Calendar calStartofDay = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
calStartofDay.set(Calendar.YEAR, 2017);
calStartofDay.set(Calendar.MONTH, 0);
calStartofDay.set(Calendar.DAY_OF_MONTH, 21);
calStartofDay.set(Calendar.HOUR_OF_DAY, 00);
calStartofDay.set(Calendar.MINUTE, 0);
calStartofDay.set(Calendar.SECOND, 1);
Calendar calBST = Calendar.getInstance(TimeZone.getTimeZone("Europe/London"));
calBST.setTimeInMillis(calStartofDay.getTimeInMillis());
// use this to check the time
System.out.printf("%tc%n", calBST);
Also, from the Calendar docs, be careful about this:
set(f, value) changes calendar field f to value. In addition, it sets
an internal member variable to indicate that calendar field f has been
changed. Although calendar field f is changed immediately, the
calendar's time value in milliseconds is not recomputed until the next
call to get(), getTime(), getTimeInMillis(), add(), or roll() is made.
Thus, multiple calls to set() do not trigger multiple, unnecessary
computations. As a result of changing a calendar field using set(),
other calendar fields may also change, depending on the calendar
field, the calendar field value, and the calendar system. In addition,
get(f) will not necessarily return value set by the call to the set
method after the calendar fields have been recomputed. The specifics
are determined by the concrete calendar class.
I need to compare the time a local file was downloaded with a time in the future/past to see if the file needs to be re-downloaded to update it. I can get the time the local file was last downloaded with :
long timeSinceCreateFile = myFile.lastModified();
What I need is to check timeSinceCreateFile with a time that is the NEXT Friday at 21:30hs and if the current time: System.currentTimeMillis()
is in the future to this then re-download the file.
I've read heaps on Calendar, Time, Date, Joda-Time etc. but have not been able to figure out how to get a moment in time as a specific Day, Hour, Minuet, etc. that is RELATIVE to timeSinceCreateFile
Edit
I need to know the time in milliseconds between when a file was downloaded (or last modified) long timeSinceCreateFile = myFile.lastModified(); and the FOLLOWING Friday at 21:30hs (as in the Friday at 21:30hrs AFTER timeSinceCreateFile)
I can then compare the "FOLLOWING FRIDAY AT 21:30hrs" milliseconds to the current time 'System.currentTimeMillis()` and if one is greater than the other re-download the file.
Hope this clarified my question, if not let me know because I really need help with this.
Thanks.
Your temporal condition "next Friday at 21:30" is hard to realize in standard Java-library using java.util.Calendar and java.util.Date.
In Joda-Time it also requires a non-trivial workaround (again with loop).
In Java-8 (new time library JSR-310 in package java.time) an acceptable solution using specialized methods in TemporalAdjusters is possible, but since you operate on Android, this is not the way to go.
Instead here an alternative solution in my library Time4J which does not need any error-prone loops or complex conditions:
import static net.time4j.PlainDate.DAY_OF_WEEK;
import static net.time4j.Weekday.FRIDAY;
File myFile = new File("");
long timeSinceCreateFile = myFile.lastModified();
// conversion to global timestamp in Time4J-format
Moment fileTSP = TemporalTypes.MILLIS_SINCE_UNIX.transform(timeSinceCreateFile);
// what ever you need (or just TZID timezone = Timezone.ofSystem().getID();)
TZID timezone = AMERICA.MONTREAL;
// "next friday" is a local time condition => convert to local timestamp
PlainTimestamp localTSP = fileTSP.toZonalTimestamp(timezone);
PlainTime walltime2130 = PlainTime.of(21, 30);
// move to next time 21:30 (possibly on next day) and then to next or same Friday
localTSP =
localTSP.with(PlainTime.COMPONENT.setToNext(walltime2130))
.with(DAY_OF_WEEK.setToNextOrSame(FRIDAY));
// convert current time to local timestamp and compare at 21:30
boolean downloadNeeded = SystemClock.inZonalView(timezone).now().isAfter(localTSP);
GregorianCalendar ? set the date to your year, month, day, 21:30, set day of week to friday. Use getTime to get a long millisecs. This will give you a UNIX time for some friday 21:30 close to your date. Keep adding or removing the number of milliseconds in a week until the time minus your file time is in the range [0 number of milliseconds in a week]. Warning with month, it's 0 based.
public static void main(String[] args){
long fileCreateTime = new Date().getTime();
GregorianCalendar calendar = new GregorianCalendar();
calendar.setTime(new Date(fileCreateTime));
calendar.set(Calendar.DAY_OF_WEEK, Calendar.FRIDAY);
calendar.set(Calendar.HOUR_OF_DAY, 21);
calendar.set(Calendar.MINUTE, 30);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
long MILLISECS_IN_A_WEEK = 7*24*60*60*1000;
long calendarMillisecs = calendar.getTime().getTime();
while(calendarMillisecs<fileCreateTime){
calendarMillisecs += MILLISECS_IN_A_WEEK;
}
while(calendarMillisecs>fileCreateTime+MILLISECS_IN_A_WEEK){
calendarMillisecs -= MILLISECS_IN_A_WEEK;
}
System.out.println(new Date(calendarMillisecs));
}
Ugly, but will work.
Avoid java.util.Date & .Calendar
Avoid java.util.Date and .Calendar because they are notoriously troublesome, flawed, and confusing. Use either Joda-Time or the new java.time package in Java 8.
Joda-Time
In Joda-Time 2.4.
DateTimeZone timeZone = DateTimeZone.forID( "America/Montreal" );
DateTime start = DateTime.now( timeZone );
// DateTime start = new DateTime( fileLastModifiedMillis, timeZone );
DateTime dateTime = start;
while ( dateTime.getDayOfWeek() != DateTimeConstants.FRIDAY ) {
dateTime = dateTime.plusDays( 1 );
}
To compare…
boolean isLate = oneDateTime.isAfter( someOtherDateTime );
I am very confused on how I can convert a given time like 9:30pm into milliseconds because I need to run a code if it is past a certain time. I already know how to get the current time in milliseconds by the following code:
long timestamp = System.currentTimeMillis();
But how would I convert 9:30pm into milliseconds? I have been researching for hours now and I can only seem to find out how to get the current time.
My application needs to check if it is 9:30pm or past and if so, run a toast message.
The fastest and correct way to do it on Android is to use Calendar. You can make Calendar instance static and reuse it whenever you need it.
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR, 9);
calendar.set(Calendar.MINUTE, 30);
calendar.set(Calendar.AM_PM, Calendar.PM);
long timeInMillis = calendar.getTimeInMillis();
I do not need to check time in milliseconds, you can compare current time with desired values using Calendar class:
Calendar calendar = Calendar.getInstance();
int hour = calendar.get(Calendar.HOUR_OF_DAY);
int minute = calendar.get(Calendar.MINUTE);
if (hour > 21 || (hour == 21 && minute >= 30)) {
doSomeJob();
}
Note that this code will not work after a midnight.
If you need time in milliseconds for 9:30pm today, you should use Calendar object to build date and time you need.
// init calendar with current date and default locale
Calendar cal = Calendar.getInstance(Locale.getDefault());
cal.setTime(new Date());
// set new time
cal.set(Calendar.HOUR_OF_DAY, 21);
cal.set(Calendar.MINUTE, 30);
cal.set(Calendar.SECOND, 0);
// obtain given time in ms
long today930PMinMills = cal.getTimeInMillis();
No need for milliseconds if you have a decent date-time library.
You can use the Joda-Time library on Android.
DateTime dateTime = new DateTime( 2014, 1, 2, 3, 4, 5 ); // Year, month, day, hour, minute, second.
boolean isNowAfterThatDateTime = DateTime.now().isAfter( dateTime );
Why don't you do it with a constant? You said that you need to check if is past 9;30. So convert that time to milliseconds and use it ad a constant. 21:30 = (21 * 60 + 30) * 60 * 1000 will give u the 9;30 in milliseconds to compare with the current time that u get in milliseconds
I have the following code in groovy to get current time in hours.
def now = new Date()
def time = now.getHours()
but the getHour() method is deprecated. What are the disadvantages if I use this method and the what is the alternative to this method in groovy/Java ?
Use Calendar,
Calendar cal=Calendar.getInstance();//it return same time as new Date()
def hour = cal.get(Calendar.HOUR_OF_DAY)
For details, read this docs.
Try using Joda Time instead of standard java.util.Date classes. Joda Time library has much better API for handling dates.
DateTime dt = new DateTime(); // current time
int month = dt.getMonth(); // gets the current month
int hours = dt.getHourOfDay(); // gets hour of day
You can use the traditional classes like this to fetch fields from given Date instance.
Date date = new Date(); // given date
Calendar calendar = GregorianCalendar.getInstance(); // creates a new calendar instance
calendar.setTime(date); // assigns calendar to given date
calendar.get(Calendar.HOUR_OF_DAY); // gets hour in 24h format
calendar.get(Calendar.HOUR); // gets hour in 12h format
calendar.get(Calendar.MONTH); // gets month number, NOTE this is zero based!
You can use Joda-time for get current time or getHours
I need to get the mobile TimeZone comparing to GMT in Android. I only could see one function returns that but as String:
Calendar c = Calendar.getInstance();
TimeZone tz = c.getTimeZone();
tz.getID();
This is the description of getID():
Returns the ID of this TimeZone, such as America/Los_Angeles, GMT-08:00 or UTC.
The problem is I need to get that as Integer like +3, -5...
You should be able to calculate the difference based on the TimeZone getOffset() value, see http://developer.android.com/reference/java/util/TimeZone.html#getOffset(long)
public static String getCurrentTimezoneOffset() {
TimeZone tz = TimeZone.getDefault();
Calendar cal = GregorianCalendar.getInstance(tz);
int offsetInMillis = tz.getOffset(cal.getTimeInMillis());
String offset = String.format("%02d:%02d", Math.abs(offsetInMillis / 3600000), Math.abs((offsetInMillis / 60000) % 60));
offset = (offsetInMillis >= 0 ? "+" : "-") + offset;
return offset;
}
Use TimeZone.getOffset. Be aware that the time difference can change due to daylight saving time and that can widely vary per country and day of year. You should therefore not rely on that offset number throughout the year. Instead it is more reliable to use the TimeZone identifier instead.