I have a integer representing the milliseconds that have passed since 12:00 A.M. on January 1, 1904. I believe this is also known as Macintosh time. It is the base time used by the original Mac OS.
Normally I would do:
int millis = 1284543608;
Date date = new Date(millis);
System.out.println(date);
However, this uses the Unix epoch and will thus not return an accurate date.
How would you print the date using milliseconds obtained from Macintosh time?
Calendar macEpoch = Calendar.getInstance();
macEpoch.setTimeInMillis(0);
macEpoch.set(1904,0, 1, 0, 0, 0);
//On a mac
Calendar macTimeForToday = Calendar.getInstance();
System.out.println("ms since mac epoch: " + macTimeForToday.getTimeInMillis());
System.out.println("ms since epoch: " + (macTimeForToday.getTimeInMillis() + macEpoch.getTimeInMillis()));
Notice that the whole translation occurs when you add -2082880800000L to macTime.getTimeInMillis()
So we know the epoch for both, we need to calculate the difference between the two...
We can start with a standard Calendar out get the time in milliseconds
Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, 1904);
cal.set(Calendar.DATE, 1);
cal.set(Calendar.MONTH, Calendar.JANUARY);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
Which returns -2082880800000. So between the Mac time and the Java time, there is a difference of 2082880800000 milliseconds....I'd probably store this somewhere.
Any time you need to convert from Mac time to Java time, you will need subtract this value from the Mac time to bring it line with the Java Time...
long javaTime = macTime - 2082880800000L;
For example...
Related
I'm setting time using Timestamp class with current time. I'm setting the time with the Calendar class first by DAY_OF_WEEK and second with DAY_OF_MONTH. I’m getting the same output every time. Then what is the diffrence between DAY_OF_MONTH and DAY_OF_WEEK?
Timestamp followUpDateBegins = new Timestamp(System.currentTimeMillis());
Calendar cal = Calendar.getInstance();
cal.setTime(followUpDateBegins);
cal.add(Calendar.DAY_OF_WEEK, -30);
cal.set(Calendar.HOUR, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
followUpDateBegins.setTime(cal.getTime().getTime());
System.out.println("followUpDateBegins "+followUpDateBegins);
OR
Timestamp followUpDateBeginsSecond = new Timestamp(System.currentTimeMillis());
cal.setTime(followUpDateBeginsSecond);
cal.add(Calendar.DAY_OF_MONTH, -30);
cal.set(Calendar.HOUR, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
followUpDateBeginsSecond.setTime(cal.getTime().getTime());
System.out.println("followUpDateBegins" + followUpDateBeginsSecond);
DAY_OF_WEEK is the day of the week (7 days), DAY_OF_MONTH is the day of the month (<=31 days)
If you use add
cal.add(Calendar.DAY_OF_WEEK, -30); is the same as cal.add(Calendar.DAY_OF_MONTH, -30);
Also DATE and DAY_OF_YEAR will act the same - because you modify Days in both cases and you just go 30 days behind.
But if your calendar is set to 15th of April for example and you do
cal.get(Calendar.DAY_OF_MONTH) and cal.get(Calendar.DAY_OF_WEEK) they will return different results.
As explained in the other answers, adding both fields results in the same date, which is a bizarre implementation detail, IMO. We can see that from the source code, there's a switch statement where both fields are considered "the same" when adding:
case DAY_OF_MONTH: // synonym of DATE
case DAY_OF_YEAR:
case DAY_OF_WEEK:
Alghough it doesn't make sense "adding days of week" (IMHO - because in the end you just add days, no matter if it's in the same week, month or whatever, and that's it), that's the way it's implemented. This API is really confusing...
Another detail is that Calendar.getInstance() already returns the current date/time - it internally calls System.currentTimeMillis(), so creating a Timestamp just to set it in the calendar is redundant. You could just do:
// create the calendar
Calendar cal = Calendar.getInstance();
// do your stuff
...
// create the timestamp
Timestamp followUpDateBeginsSecond = new Timestamp(cal.getTimeInMillis());
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 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
Given the assignment t = System.currentTimeMillis(), accrued at some point in the past, how do I get the millis of the same day as t in 12 pm and the day after 12 pm?
Note: this is timezone dependent. You can do as such:
import static java.util.Calendar.*;
final Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(yourValue);
cal.set(HOUR_OF_DAY, 12);
cal.set(MINUTE, 0);
cal.set(SECOND, 0);
cal.set(MILLISECOND, 0);
// cal.getTimeInMillis() contains the wanted day at 12pm
cal.add(DAY_OF_YEAR, 1);
// cal.getTimeInMillis() now contains the wanted day plus one at 12pm
But do yourself a favour and use Joda Time, it is much easier to use in this case:
final DateTime dayAt12pm = new DateTime(yourValue).toDateMidnight()
.plusHours(12);
// dayAt12pm.getMillis() contains the wanted day at 12pm
// next day at 12pm: dayAt12pm.plusDays(1).getMillis()
//plug your "T" here.
long t = System.currentTimeMillis();
Date date = new Date(t);
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
Calendar startOfDay = Calendar.getInstance();
startOfDay.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH));
startOfDay.set(Calendar.HOUR, 12);
startOfDay.set(Calendar.MINUTE, 0);
startOfDay.set(Calendar.SECOND, 0);
startOfDay.set(Calendar.MILLISECOND, 0);
Date startOfDayDate = startOfDay.getTime();
System.err.println("12PM on time t is " + startOfDayDate);
startOfDay.add(Calendar.HOUR, 24);
startOfDayDate = startOfDay.getTime();
System.err.println("12PM day after t is " + startOfDayDate);
One way would be to create a Date from it and then use the Calendar class.
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);