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
Related
This Java code, given a date as a string, is supposed to print the epoch timestamp for the same date at the midnight for the CET zone (supposing I'm not in the same zone).
public static void main(String[] args) throws ParseException {
String dateStr = "1995-06-06";
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
formatter.setTimeZone(TimeZone.getTimeZone("CET"));
Date date = formatter.parse(dateStr);
Calendar c = new GregorianCalendar();
c.setTimeZone(TimeZone.getTimeZone("CET"));
c.setTime(date);
c.set(Calendar.HOUR_OF_DAY, 0);
c.set(Calendar.MINUTE, 0);
c.set(Calendar.SECOND, 0);
c.set(Calendar.MILLISECOND, 0);
System.out.println("Epoch timestamp = " + c.getTime().getTime());
}
If I run the above program I should get printed:
Epoch timestamp = 802389600000
And I can verify it's correct here:
https://www.epochconverter.com/timezones?q=802389600&tz=Europe%2FMalta
Now, that works for most of the dates. However, there are some bizarre dates like "1975-09-19", where it doesn't work. In fact, It generates 180313200000 as a timestamp, which gives 1am and not midnight:
https://www.epochconverter.com/timezones?q=180313200&tz=Europe%2FMalta
Can you explain why? What am I missing?
Time zone discrepancy
Your Java code uses CET, which is not really a time zone (for example because most of the areas where it’s used use CEST instead for most of the year). Java translates CET to Europe/Paris. France and Paris did not use summer time (DST) in 1975. It was reintroduced in March 1976.
Your link to the epoch converter specifies Malta time zone (Europe/Malta). Malta did use summer time in 1975: it was on CEST from 20 April to 21 September that year.
This explains the difference in your results.
In Java code
If you wanted Malta time:
String dateStr = "1975-09-19";
long epochTimestamp =
LocalDate
.parse(dateStr)
.atStartOfDay(ZoneId.of("Europe/Malta"))
.toInstant()
.toEpochMilli();
System.out.println("Epoch timestamp = " + epochTimestamp);
This prints:
Epoch timestamp = 180309600000
And the epoch converter that you linked to is happy to agree:
Conversion results (180309600)
180309600 converts to Friday September 19, 1975 00:00:00 (am) in
time zone Europe/Malta (CEST) The offset (difference to Greenwich
Time/GMT) is +02:00 or in seconds 7200. This date is in daylight
saving time.
In Java do use java.time, the modern Java date and time API, for your date and time work. It is so much nicer to work with compared to the old date and time classes like SimpleDateFormat, TimeZone, Date and Calendar. Also setting the hours, etc., to 0 is not the correct way to get the first moment of the day. There are cases where summer time begins at the start of the day, so the first moment of the day is 01:00:00. Java knows that, so the atStartOfDay method will give you the correct forst moment of the day in question.
And no matter if using outdated or modern classes always specify time zone in the region/city format, for example Europe/Paris or Europe/Malta. The three, four and five letter time zone abbreviations are often ambiguous and often not true time zones, so not to be relied on.
Links
Time Zone in Paris, Île-de-France, France
Time Zone in Valletta, Malta
Oracle tutorial: Date Time explaining how to use java.time.
There seems to be a difference concerning daylight saving time between your date examples.
If I use java.time (which should always be used since Java 8), I get results with different offsets:
"+02:00" for "1995-06-06" and
"+01:00" for "1975-09-19"
This is how I got the results:
public static void main(String[] args) {
// provide two sample dates
String workingDateStr = "1995-06-06";
String failingDateStr = "1975-09-19";
// and a formatter that parses the format
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
// then parse them to date objects that don't know about time or zone
LocalDate workingDate = LocalDate.parse(workingDateStr, dtf);
LocalDate failingDate = LocalDate.parse(failingDateStr, dtf);
/*
* then create an objects that are aware of time and zone
* by using the parsed dates, adding a time of 00:00:00 and a zone
*/
ZonedDateTime workingZdt = ZonedDateTime.of(workingDate, LocalTime.MIN, ZoneId.of("CET"));
ZonedDateTime failingZdt = ZonedDateTime.of(failingDate, LocalTime.MIN, ZoneId.of("CET"));
// finally, print different representations of the results
System.out.println(workingZdt + " ——> " + workingZdt.toInstant().toEpochMilli());
System.out.println(failingZdt + " ——> " + failingZdt.toInstant().toEpochMilli());
}
Output:
1995-06-06T00:00+02:00[CET] ——> 802389600000
1975-09-19T00:00+01:00[CET] ——> 180313200000
That means you might be better off using specific offsets instead of zones.
This issue could be due to the timing of the introduction of Daylight Saving Time in Malta, have a look at the following code and its output:
public static void main(String[] args) {
// provide two sample dates
String failingDateStr = "1975-09-19";
// and a formatter that parses the format
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
// then parse them to date objects that don't know about time or zone
LocalDate failingDate = LocalDate.parse(failingDateStr, dtf);
/*
* then create an objects that are aware of time and zone
* by using the parsed dates, adding a time of 00:00:00 and a zone
*/
ZonedDateTime failingZdt = ZonedDateTime.of(failingDate, LocalTime.MIN, ZoneId.of("CET"));
// add some years to 1975 and...
for (int year = 0; year < 4; year++) {
// ... print the different representations of the result
System.out.println(failingZdt.plusYears(year) + " ——> "
+ failingZdt.plusYears(year).toInstant().toEpochMilli());
}
}
Output:
1975-09-19T00:00+01:00[CET] ——> 180313200000
1976-09-19T00:00+01:00[CET] ——> 211935600000
1977-09-19T00:00+02:00[CET] ——> 243468000000
1978-09-19T00:00+02:00[CET] ——> 275004000000
This output indicates an introduction in 1977... Is that correct?
Supposing the time zone is CST. I have a webservice that returns a java.util.Date as "2020-03-14". I want to convert it to OffsetDateTime in the format "2020-03-14 05:59:59.9999990 +00:00". The below code does not have the time information.
Date endDate = someService.getEndDate();
Instant instant = Instant.ofEpochMilli(endDate.getTime());
OffsetDateTime offsetEndDt = OffsetDateTime.ofInstant(instant, ZoneOffset.UTC);
The value of offsetEndDt is 2020-03-14T05:00Z
An OffsetDateTime does not have any format itself, it holds the information about the date and the time. If you create an OffsetDateTime just from a date it will get the default time information of 0 hours, minutes, seconds and nanos.
You can output it in various formats using a DateTimeFormatter and create a new instance of OffsetDateTime adding temporal units to an existing one like this:
public static void main(String[] args) {
// example OffsetDateTime
OffsetDateTime offsetEndDt = OffsetDateTime.of(2020, 3, 14, 0, 0, 0, 0,
ZoneOffset.UTC);
// define a formatter for the output
DateTimeFormatter myFormatter = DateTimeFormatter
.ofPattern("yyyy-MM-dd'T'HH:mm:ss.nnnnnnnnn xxx");
// print it using the previously defined formatter
System.out.println(offsetEndDt.format(myFormatter));
// create a new OffsetDateTime with time information
OffsetDateTime realEndOfDay = offsetEndDt
.withHour(23)
.withMinute(59)
.withSecond(59)
.withNano(999999000);
// print that, too
System.out.println(realEndOfDay.format(myFormatter));
}
It produces the following output using the pattern your example desired output has:
2020-03-14T00:00:00.000000000 +00:00
2020-03-14T23:59:59.999999000 +00:00
First allow me to suggest that you represent the end of your interval NOT as one microsecond before the next day begins, but AS the first moment of the next day exclusive. So a point in time is inside your interval if it is strictly before your end time. This is philosophically more correct. And it rules out the possibility of falsely excluding a point in time within the last 999 nanoseconds of the day from your interval.
// Construct an example java.util.Date for the demonstration
Instant exampleInstant = LocalDate.of(2020, Month.MARCH, 14)
.atStartOfDay(ZoneId.systemDefault())
.toInstant();
Date enddt = Date.from(exampleInstant);
System.out.println("Example java.util.Date: " + enddt);
OffsetDateTime edt = enddt.toInstant()
.atZone(ZoneId.systemDefault())
.plusDays(1)
.truncatedTo(ChronoUnit.DAYS)
.toOffsetDateTime();
System.out.println("End: " + edt);
As one interpretation of EST (of several possible) I have run this code in America/Atikokan time zone (America/Winnipeg gave me EDT). The output was:
Example java.util.Date: Sat Mar 14 00:00:00 EST 2020
End: 2020-03-15T00:00-05:00
If you insist on getting the time 1 microsecond before the new day starts, subtract a microsecond:
OffsetDateTime edt = enddt.toInstant()
.atZone(ZoneId.systemDefault())
.plusDays(1)
.truncatedTo(ChronoUnit.DAYS)
.minus(1, ChronoUnit.MICROS)
.toOffsetDateTime();
End: 2020-03-14T23:59:59.999999-05:00
The below lines of code worked.
Date enddt = someService.getEndDate();
Calendar cal = Calendar.getInstance();
cal.setTime(enddt);
int year = cal.get(Calendar.YEAR);
int month = cal.get(Calendar.MONTH);
int day = cal.get(Calendar.DAY_OF_MONTH);
OffsetDateTime edt = OffsetDateTime.of(year,month+1,day,23,59,59,999999000,OffsetDateTime.now().toZonedDateTime().getOffset());
I have two java.time.Instant objects
Instant dt1;
Instant dt2;
I want to get time (only hours and minutes without date) from dt2 and set it to dt1. What is the best way to to this? Using
dt2.get(ChronoField.HOUR_OF_DAY)
throws java.time.temporal.UnsupportedTemporalTypeException
You have to interpret the Instant at some time zone to get ZonedDateTime. As an Instant measures the ellapsed seconds and nano seconds from epoch 1970-01-01T00:00:00Z you should use UTC to get the same time as the Instant would print. (Z ≙ Zulu Time ≙ UTC)
Getting the time
Instant instant;
// get overall time
LocalTime time = instant.atZone(ZoneOffset.UTC).toLocalTime();
// get hour
int hour = instant.atZone(ZoneOffset.UTC).getHour();
// get minute
int minute = instant.atZone(ZoneOffset.UTC).getMinute();
// get second
int second = instant.atZone(ZoneOffset.UTC).getSecond();
// get nano
int nano = instant.atZone(ZoneOffset.UTC).getNano();
There are also methods to get days, month and year (getX).
Setting the time
Instants are immutable so you can only "set" the time by creating a copy of your instant with the given time change.
instant = instant.atZone(ZoneOffset.UTC)
.withHour(hour)
.withMinute(minute)
.withSecond(second)
.withNano(nano)
.toInstant();
There are also methods to alter days, month and year (withX) as well as methods to add (plusX) or subtract (minusX) time or date values.
To set the time to a value given as a string use: .with(LocalTime.parse("12:45:30"))
Instant does not have any hour / minute. Please read the documentation of Instant class : https://docs.oracle.com/javase/8/docs/api/java/time/Instant.html
If you use System Timezone to convert the Instant , you can use something like this :
LocalDateTime ldt1 = LocalDateTime.ofInstant(dt1, ZoneId.systemDefault());
LocalDateTime ldt2 = LocalDateTime.ofInstant(dt2, ZoneId.systemDefault());
ldt1 = ldt1
.withHour(ldt2.getHour())
.withMinute(ldt2.getMinute())
.withSecond(ldt2.getSecond());
dt1 = ldt1.atZone(ZoneId.systemDefault()).toInstant();
Convert first the Instant to LocalDateTime, and use UTC as its timezone, then you can get its hours.
import java.time.*
LocalDateTime.ofInstant(Instant.now(), ZoneOffset.UTC).getHour()
While the upper answer is a good, I used it but in Kotlin. Thankyou #frido
while (startDate.isBefore(endDate)) {
val year: Int = startDate.atZone(ZoneOffset.UTC).year
val month: Int = startDate.atZone(ZoneOffset.UTC).monthValue
val day: Int = startDate.atZone(ZoneOffset.UTC).dayOfMonth
System.out.printf("%d.%d.%d\n", day, month, year)
startDate = startDate.atZone(ZoneOffset.UTC).withDayOfMonth(
day + 1
).toInstant()
}
This is continuation to one of my previous question where I am not able to parse the date which is resolved now. In the below code, I have a date string and I know the time zone for the date string even though the string itself doesn't contain it. Then I need to convert the date into EST time zone.
String clientTimeZone = "CST6CDT";
String value = "Dec 29 2014 11:36PM";
value=StringUtils.replace(value, " ", " ");
DateTimeFormatter df = DateTimeFormat.forPattern("MMM dd yyyy hh:mma").withZone(DateTimeZone.forID(clientTimeZone));
DateTime temp = df.parseDateTime(value);
System.out.println(temp.getZone().getID());
Timestamp ts1 = new Timestamp(temp.getMillis());
DateTime date = temp.withZoneRetainFields(DateTimeZone.forID("EST"));//withZone(DateTimeZone.forID("EST"));
Timestamp ts = new Timestamp(date.getMillis());
System.out.println(ts1+"="+ts);
When I am running the code I am expecting ts1 to remain same and ts to be up by 1 hr. But iam getting below which I don't understand. I thought EST is one hour ahead of CST and so if it is 11 in CST, it should be 12 in EST. Also there seems to be offset by about eleven and half hours. Any clues on what I am missing.
2014-12-30 11:06:00.0=2014-12-30 10:06:00.0
I think the below code will help you.
String clientTimeZone = "CST6CDT";
String toStimeZone = "EST";
String value = "Dec 29 2014 11:36PM";
TimeZone fromTimeZone = TimeZone.getTimeZone(clientTimeZone);
TimeZone toTimeZone = TimeZone.getTimeZone(toStimeZone);
Calendar calendar = Calendar.getInstance();
calendar.setTimeZone(fromTimeZone);
SimpleDateFormat sf = new SimpleDateFormat("MMM dd yyyy KK:mma");
Date date = sf.parse(value);
calendar.setTime(date);
System.out.println(date);
calendar.add(Calendar.MILLISECOND, fromTimeZone.getRawOffset() * -1);
if (fromTimeZone.inDaylightTime(calendar.getTime())) {
calendar.add(Calendar.MILLISECOND, calendar.getTimeZone().getDSTSavings() * -1);
}
calendar.add(Calendar.MILLISECOND, toTimeZone.getRawOffset());
if (toTimeZone.inDaylightTime(calendar.getTime())) {
calendar.add(Calendar.MILLISECOND, toTimeZone.getDSTSavings());
}
System.out.println(calendar.getTime());
Copied from : http://singztechmusings.wordpress.com/2011/06/23/java-timezone-correctionconversion-with-daylight-savings-time-settings/
The method withZoneRetainFields() preserves the fields in the timezone CST (= UTC-06) hence your local timestamp (as LocalDateTime) but combines it with a different timezone (EST = UTC-05) which is one hour ahead in offset and result in a different instant. You should it interprete it this way: The same local time happens one hour earlier in New York compared to Chicago.
The rule is to subtract positive offsets and to add negative offsets in order to make timestamp representations of instants comparable (normalizing to UTC offset).
Alternatively: Maybe you don't want this but want to preserve the instant instead of the local fields. In this case you have to use the method withZone().
Side notice: Effectively, you compare the instants represented by the variables temp and date and finally use your default timezone to print these instants in the JDBC-escape-format (explanation - you implicitly use Timestamp.toString()). I would rather recommend to use a dedicated instant formatter for this purpose or simpler (to have the offsets in focus):
System.out.println(temp.toInstant() + " = " + date.toInstant());
I have dates in the format 20Jan2013, 08Aug2012 etc, with their own specific timezones. So for example, 20Jan2013 might have a timezone ID of Australia/Melbourne, and 08Aug2012 might have an ID of Europe/London. What I want to do is, based on these timezones and the dates, calculate the UTC offset for that timezone on the given date. I've come up with this so far:
DateTimeFormatter dtf = DateTimeFormat.forPattern("ZZ");
DateTimeFormatter dtf1 = DateTimeFormat.forPattern("ddMMMYYYY");
DateTimeZone zone = DateTimeZone.forID("Australia/Melbourne");
DateTime thisDate = dtf1.parseDateTime("30Jul2013");
System.out.println("\nZone: " + thisDate.withZone(zone));
This gives me the output:
Zone: 2013-07-30T00:00:00.000+10:00
This is correct, but I would like to extract just the UTC offset from this, which in this case is +10:00. I've looked for ways to do this but can't find anything. Is there any way I can do this? The only option I see is to convert the output to a String and use the substring method to get the UTC offset.
The above code does take DST (Daylight Saving Time) into account. So for example if I had:
DateTime thisDate = dtf1.parseDateTime("30Jan2013");
The output would be: 2013-01-30T00:00:00.000+11:00
(+11:00 at the end instead of +10:00)
So basically all I need to do is find a way to extract +11:00 from 2013-07-30T00:00:00.000+11:00. Please help!
Simple Method for Obtaining Timezone Name and Offset in Hours
public static String getCurrentTimeZoneOffset() {
DateTimeZone tz = DateTimeZone.getDefault();
Long instant = DateTime.now().getMillis();
String name = tz.getName(instant);
long offsetInMilliseconds = tz.getOffset(instant);
long hours = TimeUnit.MILLISECONDS.toHours( offsetInMilliseconds );
String offset = Long.toString( hours );
return name + " (" + offset + " Hours)";
// Example: "Mountain Standard Time (-7 Hours)"
}
Couple caveats:
This gets the default DateTimeZone from JodaTime. You can modify it to accept a specific DateTimeZone that is passed into the method.
This returns it in a format like "Mountain Standard Time (-7 Hours)" but you can format it as you see fit quite easily.
Hope that helps.
JP
In order for Joda to give the correct offset, you must provide a datetime instant.Without a datetime instant, it is impossible to calculate the offset since we have different offsets(daylight savings). This is how I would use Joda to get offset in + HH:mm format :
int offsetInMillis = DateTimeZone.forID(zoneId).getOffset(new DateTime().getMillis());
String offset = String.format("%02d:%02d", Math.abs(offsetInMillis / 3600000),
Math.abs((offsetInMillis / 60000) % 60));
offset = (offsetInMillis >= 0 ? "+" : "-") + offset;
If you just need the timezone offset, use DateTimeZone.forID() to get the time zone and then tz.getOffset(instant) to get the offset to UTC in milliseconds.
It may look odd that you need an instant to calculate the offset to UTC but this is necessary to take Daylight Savings into account as well as changes in the timezone. Yes, countries change their timezones once in a while:
Why does timezone data change?
Timezone settings are adopted locally, and there is no world timezone authority.
EDIT This gives you the correct result:
DateTimeFormatter dtf1 = DateTimeFormat.forPattern("ddMMMYYYY");
DateTimeZone zone = DateTimeZone.forID("Australia/Melbourne");
DateTime thisDate = dtf1.parseDateTime("30Jul2013").withZone(zone);
assertEquals( 10 * CommonConstants.MILLISECONDS_PER_HOUR,
zone.getOffset( thisDate ) );
thisDate.get
Java 8 introduced better Date and Time handling to address some of the language's previous limitations in that area. A few of my projects have started to use it rather than Joda.
Using the java.time package:
ZonedDateTime dateTime = LocalDate.of(2013 , 1 , 20).atStartOfDay( ZoneId.of("Australia/Melbourne"));
ZoneOffset zo = dateTime.getOffset();
int offset = zo.getTotalSeconds();
long hours = TimeUnit.SECONDS.toHours(offset);
long minutes = TimeUnit.SECONDS.toMinutes(offset % 3600);
The hours variable is set to 11 and the minutes to 0.
It also calculates the minutes-offset, for time zones that are partial hours, such as Newfoundland and Labrador in eastern Canada:
ZonedDateTime dateTime = LocalDate.of(2013, 1, 20).atStartOfDay( ZoneId.of("Canada/Newfoundland"));
In this case, the offset is -03:30 (three and a half hours behind UTC), hours is -3 and minutes is -30.
For the String representation, rather than the integer number of hours and minutes, use the ZoneOffset's toString() method. So for the example above, use:
String offsetString = zo.toString();
When you know offset and timestamp so in order to get current time you can use
public static String formatMonthDayMinuteByGivenUtcOffset(long timestamp, int offset) {
return JODA_FORMATTER.print(createDateTime(timestamp, offset));
}