First off I'm new in this incredible community. This is an amazing site. I'm happy to be part finally.
Every day I have to insert yesterday's data in the DB. For example, today May 22, I have to insert the data of the 21st from 00:00:00 to 23:59:59 in epoch time.
So far I get the epoch time from today with
long now = Instant.now().toEpochMilli();
How could I get yesterday's epoch time? and store the range of hours in two variables? Like
String startDay = 21/05/2020 00:00:00
String endDay = 21/05/2020 23:59:59
You can use java LocalDate like this:
final LocalDate now = LocalDate.now();
final LocalDate yesterday = now.minusDays(1);
final LocalDateTime start = yesterday.atStartOfDay();
final LocalDateTime end = yesterday.atTime(LocalTime.MAX);
And then format date to your desired format.
You can use a ZonedDateTime as an alternative to the answer given by #ArtyomRebrov.
It will take the system time zone implicitly if you don't provide a specific one.
See this example:
public static void main(String[] args) {
// get a datetime plus time zone information using the system time zone
ZonedDateTime startToday = ZonedDateTime.now()
// subtract a day
.minusDays(1)
// and take the minimum time a day can have
.with(LocalTime.MIN);
// use the same datetime to create the end of the day using the maximum time for a day
ZonedDateTime endToday = startToday.with(LocalTime.MAX);
// then print the results in date-time format and as epoch millis
System.out.println("Yesterday's beginning:\t" + startToday + "\t\t\t| "
+ startToday.toInstant().toEpochMilli());
System.out.println("Yesterday's end:\t" + endToday
+ "\t| " + endToday.toInstant().toEpochMilli());
}
Which outputs (on my maching in Germany):
Yesterday's beginning: 2020-05-21T00:00+02:00[Europe/Berlin] | 1590012000000
Yesterday's end: 2020-05-21T23:59:59.999999999+02:00[Europe/Berlin] | 1590098399999
I need to calculate period between two dates, one date is now. And I'm using SimpleDateFormat for formatting date.
public String getPeriod(Date endDate) {
String format;
Date now = new Date();
long period = endDate.getTime() - now.getTime();
if (now.after(endDate)) {
return "passed";
} else {
if (period < 1000 * 60 * 60)
format = "m'M' s'S'";
else if (period < 1000 * 60 * 60 * 24)
format = "k'H' m'M'";
else
format = "'Too much'";
SimpleDateFormat formatter = new SimpleDateFormat(format);
return formatter.format(new Date(period)) + " / for testing - " + period / 3600000 + " hours";
}
}
As a result I have following input for example if endDate equals Wed Nov 12 13:30:02 EET 2014 (EST):
1 H 36 M / for testing - 22 hours
As you can see my test calculation and format's method result do not match. What am i doing wrong?
The difference is due to the timezone. For example, in my case, given as the parameter the time that would be in an hour, I get 3H as output, because the date would be Thu Jan 01 03:00:00 EET 1970. Notice the EET (I'm from Eastern Europe).
Your code would work if you'd notify java to use GMT time, as it says in the new Date(long) description:
Allocates a Date object and initializes it to represent the specified
number of milliseconds since the standard base time known as "the
epoch", namely January 1, 1970, 00:00:00 GMT.
Also, keep in mind that Date does not give perfect results. Using programatically determined dates exactly 1h appart (no millies / minutes difference), date calculations give an offset of 59 minutes, 59 seconds and 999 milies. If you require more exact values, you should use nanoseconds.
However, the other commenters are right. You should not use Java Date / Calendar in such a way, as it is a bug factory (this is only one corner case). You should check out other libraries (such as yoda time), or if you only need simple calculations such as this, do it yourself.
Hope it helps.
In my web application, I am storing all end-user's date information as UTC format in database, and before showing it to them, just converting the UTC dates to timezones of their choice.
I am using this method to convert a localtime to UTC time (while storing):
public static Date getUTCDateFromStringAndTimezone(String inputDate, TimeZone timezone){
Date date
date = new Date(inputDate)
print("input local date ---> " + date);
//Returns the number of milliseconds since January 1, 1970, 00:00:00 GMT
long msFromEpochGmt = date.getTime()
//gives you the current offset in ms from GMT at the current date
int offsetFromUTC = timezone.getOffset(msFromEpochGmt)*(-1) //this (-1) forces addition or subtraction whatever is reqd to make UTC
print("offsetFromUTC ---> " + offsetFromUTC)
//create a new calendar in GMT timezone, set to this date and add the offset
Calendar gmtCal = Calendar.getInstance(TimeZone.getTimeZone("GMT"))
gmtCal.setTime(date)
gmtCal.add(Calendar.MILLISECOND, offsetFromUTC)
return gmtCal.getTime()
}
And this method for converting UTC date to local (while showing):
public static String getLocalDateFromUTCDateAndTimezone(Date utcDate, TimeZone timezone, DateFormat formatter) {
printf ("input utc date ---> " + utcDate)
//Returns the number of milliseconds since January 1, 1970, 00:00:00 GMT
long msFromEpochGmt = utcDate.getTime()
//gives you the current offset in ms from GMT at the current date
int offsetFromUTC = timezone.getOffset(msFromEpochGmt)
print("offsetFromUTC ---> " + offsetFromUTC)
//create a new calendar in GMT timezone, set to this date and add the offset
Calendar localCal = Calendar.getInstance(timezone)
localCal.setTime(utcDate)
localCal.add(Calendar.MILLISECOND, offsetFromUTC)
return formatter.format(localCal.getTime())
}
My question is, if the end-user is within a DST zone, then how do I improve the methods to accommodate their local clock times perfectly.
If you use a custom time zone ID, like GMT+10 you will get TimeZone that does not support DST, eg TimeZone.getTimeZone("GMT+10").useDaylightTime() returns false. But if you use a supported ID eg "America/Chicago" you will get a TimeZone that supports DST. The full list of supported IDs is returned by TimeZone.getAvailableIDs(). Internally Java stores time zone info in jre/lib/zi.
I have following method which convert my custom DMY (date,month,year) object to Date.
public static Date serverCreateDateFromDMY(DMY pDMY, TimeZone pTimeZone)
{
Calendar vCalendar = Calendar.getInstance(pTimeZone);
vCalendar.set(Calendar.YEAR, pDMY.getYear());
// Below line is because DMY month counts are 1-indexed
// and Date month counts are 0-indexed
vCalendar.set(Calendar.MONTH, pDMY.getMonthOfYear() - 1);
vCalendar.set(Calendar.DAY_OF_MONTH, pDMY.getDayOfMonth());
System.out.println(vCalendar.getTime());
TimeUtilsServer.zeroCalendarHoursAndBelow(vCalendar);
System.out.println(vCalendar.getTime());
return vCalendar.getTime();
}
public static void zeroCalendarHoursAndBelow(Calendar pToZero)
{
pToZero.set(Calendar.HOUR_OF_DAY, 0);
pToZero.set(Calendar.MINUTE, 0);
pToZero.set(Calendar.SECOND, 0);
pToZero.set(Calendar.MILLISECOND, 0);
}
to serverCreateDateFromDMY() method, I am passing these arguments : DMY=20120424, and TimeZone is : America/New_York. Application is running locally in my timezone which is IST.
based in above inputs, following output is printed.
Tue Apr 24 14:43:07 IST 2012
Tue Apr 24 09:30:00 IST 2012
so as you see that in last output time is not zeroed out. any suggestions please?
#Marko, yes I come to know about DateFormat and I tried following example. but still date is printed with time and not zeroing out.
TimeZone tz = TimeZone.getTimeZone("America/New_York");
Calendar vCalendar = Calendar.getInstance(tz);
vCalendar.set(Calendar.YEAR, 2012);
vCalendar.set(Calendar.MONTH, 4 - 1);
vCalendar.set(Calendar.DAY_OF_MONTH, 24);
DateFormat df = DateFormat.getDateTimeInstance();
df.setTimeZone(tz);
System.out.println(df.format(vCalendar.getTime()));
vCalendar.set(Calendar.HOUR_OF_DAY, vCalendar.getActualMinimum(Calendar.HOUR_OF_DAY));
vCalendar.set(Calendar.MINUTE, vCalendar.getActualMinimum(Calendar.MINUTE));
vCalendar.set(Calendar.SECOND, vCalendar.getActualMinimum(Calendar.SECOND));
vCalendar.set(Calendar.MILLISECOND, vCalendar.getActualMinimum(Calendar.MILLISECOND));
System.out.println(df.format(vCalendar.getTime()));
java Date / Time API have a bad design from the time of its creation. Maybe you should take a look at some library - for example this which hides JDK API deficiencies - http://joda-time.sourceforge.net/
Internally, Date and Calendar objects are stored in UTC. When you set the fields to 0, the Calendar is updated in UTC.
When you ask the Calendar for the time, it then converts the Date to your desired Timezone, hence the difference.
... and you are 9:30h ahead of NY time. You set the time to midnight NY time and read it out as time in your zone. Note that getTime returns a Date, which is not timezone-configurable. You'll need DateFormat if you want to specify the timezone for which you print the result.
I have a milliseconds-since-local-epoch timestamp that I'd like to convert into a milliseconds-since-UTC-epoch timestamp. From a quick glance through the docs it looks like something like this would work:
int offset = TimeZone.getDefault().getRawOffset();
long newTime = oldTime - offset;
Is there a better way to do this?
Sadly, this seems to be the best way to do this:
public static Date convertLocalTimestamp(long millis)
{
TimeZone tz = TimeZone.getDefault();
Calendar c = Calendar.getInstance(tz);
long localMillis = millis;
int offset, time;
c.set(1970, Calendar.JANUARY, 1, 0, 0, 0);
// Add milliseconds
while (localMillis > Integer.MAX_VALUE)
{
c.add(Calendar.MILLISECOND, Integer.MAX_VALUE);
localMillis -= Integer.MAX_VALUE;
}
c.add(Calendar.MILLISECOND, (int)localMillis);
// Stupidly, the Calendar will give us the wrong result if we use getTime() directly.
// Instead, we calculate the offset and do the math ourselves.
time = c.get(Calendar.MILLISECOND);
time += c.get(Calendar.SECOND) * 1000;
time += c.get(Calendar.MINUTE) * 60 * 1000;
time += c.get(Calendar.HOUR_OF_DAY) * 60 * 60 * 1000;
offset = tz.getOffset(c.get(Calendar.ERA), c.get(Calendar.YEAR), c.get(Calendar.MONTH), c.get(Calendar.DAY_OF_MONTH), c.get(Calendar.DAY_OF_WEEK), time);
return new Date(millis - offset);
}
(I know that this is several months past post date, but it's a problem that is very useful to solve when working with text messages on Android. dave's answer is wrong.)
Use a Calendar to get what the offset was at the local Epoch, then add that to the local-epoch timestamp.
public static long getLocalToUtcDelta() {
Calendar local = Calendar.getInstance();
local.clear();
local.set(1970, Calendar.JANUARY, 1, 0, 0, 0);
return local.getTimeInMillis();
}
public static long converLocalTimeToUtcTime(long timeSinceLocalEpoch) {
return timeSinceLocalEpoch + getLocalToUtcDelta();
}
Using Joda Time it would be like this :
DateTime dt = new DateTime(year, month, day, hour, minute, 0, 0, DateTimeZone.forID("local");
dt.getMillis();
EDITED: Sorry, this is the correct version :
DateTime dt = new DateTime(timestamp, DateTimeZone.forID("local");
dt.getMillis();
Actually, Chris Lercher hit the nail on the head, but he only made it in a short comment, so I wanted to expand on it.
Imagine two stopwatches; one is somewhere where UTC is the local time on Jan 1, 1970, and the other stopwatch is local to your area (let's say that it's in New York, 5 hours after UTC). At UTC midnight, on Jan 1, 1970, the UTC stopwatch is started. 5 hours later, your local stopwatch is started. Those two stopwatch times differ by some amount, determined only by what the difference between UTC was from your local time at local midnight on Jan 1, 1970. Any daylight-saving shenanigans, since then, have no bearing on the difference between those stopwatches. So, any DST corrections for your present time or for the times you're converting, are irrelevant. All you need is how much later your local stopwatch started on Jan 1, 1970.
As Chris pointed out, this is just: getOffset(0L), so:
int offset = TimeZone.getDefault().getOffset(0L);
long newTime = oldTime - offset;
... should work fine. However....
To help really grasp this, note this: that "0L" in getOffset() is the milliseconds since the UTC epoch (which is the only real epoch). So, your offset variable is going to have the number of seconds of offset at midnight UTC (ie, when it was, say, 19:00 on 12/31/1969 in New York). If your local time switched to/from daylight-saving in those last hours before local midnight, then getOffset(0L) wouldn't be correct. You need to know what your daylight-saving status was at local midnight, not UTC's midnight.
I'd be surprised if this were the case, anywhere (ie, any timezone which changed to/from DST between their local midnight and UTC midnight of Jan 1, 1970). However, just for fun, a cheap hack to help guard against this would be to check if the offset changed in those hours:
// Offset at UTC midnight
int offset = TimeZone.getDefault().getOffset(0L);
long newTime = oldTime - offset;
// Offset at Local midnight
int localMidnightOffset = TimeZone.getDefault().getOffset(-offset);
Here, localMidnightOffset will be what the timezone offset was at a time -offset milliseconds after UTC midnight in 1970. If no DST change happened, then localMidnightOffset will equal offset, and you're done. If some DST change did occur, then you might have to hunt around... probably keep doing a
localMidnightOffset = TimeZone.getDefault().getOffset(-localMidnightOffset)
until it stops changing... and hope you don't get caught in an endless loop. I'm curious to see if anybody has a guaranteed-converging solution.
Kinda makes you wish the world were flat, huh?
No, that definitely won't work - it doesn't take DST into account. You can't just use getOffset(oldTime) either, as the DST may have changed between the two...
You could use getOffset(oldTime) to get an initial guess at the timestamp, then check getOffset(utcTime) to see whether they're the same or not. It gets fun, basically.
Joda Time should support this using DateTimeZone.getOffsetFromLocal but that's slightly broken (IMO) around DST transitions.
All of this really depends on what you mean by "milliseconds since local epoch". If you really mean elapsed milliseconds since local 1970, you could just find out the offset at that date, and apply that regardless. Typically (IME) a "local" millis value doesn't mean quite that though - it means "the number of millis to get to a particular date and time (e.g. April 9th 2010, 18:06pm) in UTC, but in respect of a different time zone". In other words, it can represent ambiguous or impossible date/time combinations based on DST transitions.
static final long localTimeZoneoffset = TimeZone.getDefault().getOffset(0L);
static final long dstOffset = TimeZone.getDefault().getDSTSavings();
long offsetOftime = TimeZone.getDefault().getOffset(time.getTime());
long timeinmilli = 0L;
if(offsetOftime != localTimeZoneoffset)
timeinmilli = time.getTime()+localTimeZoneoffset+dstOffset;
else
timeinmilli = time.getTime()+localTimeZoneoffset;
return new Timestamp(timeinmilli);
This worked for me to convert to UTC.
May be this can help you i have try this way. Please comment me if there is any best and optimize way to convert local time to UTC timestamp.
String mDate= "Jul 21,2016 1:23 PM";
String mDateFormat =""MMM d,yyyy h:mm a";
Call : getConvertedTimeToUTC(mDate,mDateFormat);
public String getConvertedTimeToUTC(String ourDate, String mDateFormat) {
try {
SimpleDateFormat fmt = new SimpleDateFormat(mDateFormat);
fmt.setTimeZone(TimeZone.getTimeZone("UTC"));
Date value = fmt.parse(ourDate);
if (value != null)
return String.valueOf(value.getTime() / 1000);
else
return null;
} catch (Exception e) {
ourDate = "00-00-0000 00:00";
}
return ourDate;
}
Here is the result : (Ref : check conversion)
Result 1469107380
GMT: Thu, 21 Jul 2016 13:23:00 GMT
Your time zone: Thursday 21 July 2016 06:53:00 PM IST GMT+5:30