How to add current timestamp to Date object in Java? - java

I need to pass in a Date object into a service which my API is calling. I have the info on the day, month, and year for the Date but also need a timestamp. The service is expecting it in this format:
<date>2015-04-01T00:00:00-05:00</date>
How can I add something to the Date to get this format?

Never use java.util.Date. Supplanted by java.time.Instant.
Get your date portion.
LocalDate ld = LocalDate.of( 2015 , 4 , 1 ) ;
Or use the readable Month enum.
LocalDate ld = LocalDate.of( 2015 , Month.APRIL , 1 ) ;
Get the time of day when the day starts in some particular time zone. Do not assume the day starts at 00:00:00, may be some other time such as 01:00:00. Let java.time figure that out for you.
ZoneId z = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime zdt = ld.atStartOfDay( z ) ;
Generate a string in your desired format, a standard ISO 8601 format.
DateTimeFormatter f = DateTimeFormatter.ISO_OFFSET_DATE_TIME ;
String output = zdt.format( f ) ;
To see that moment in UTC, extract a Instant.
Instant instant = zdt.toInstant() ;
Conversion
If you must inter-operate with old code not yet updated for java.time, you can call new conversion methods added to the old classes. These include Date::from( Instant ).
java.util.Date d = java.util.Date.from( instant ) ;
Going the other direction.
Instant instant = d.toInstant() ;
Get back to a time zone other than UTC.
ZonedDateTime zdt = instant.atZone( ZoneId.of( "Pacific/Auckland" ) ) ; // Same moment, different wall-clock time.

Working with dates in Java is an ugly mess, always has been. Date class is mostly deprecated now. I am using LocalDateTime where you can construct it by calling year, month, day, hour, minute, and seconds. Here is what I could come up with:
LocalDateTime ldt = LocalDateTime.of(1997, Month.SEPTEMBER, 2, 1, 23, 0);
ZonedDateTime systemTime = ldt.atZone(ZoneId.systemDefault());
DateTimeFormatter formatter = DateTimeFormatter.ISO_OFFSET_DATE_TIME; //Basil's idea
System.out.println(systemTime.format(formatter));
Output:
1997-09-02T01:23:00-05:00

You could use SimpleDateFormat for this.
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
dateFormat.format(new Date());

Related

How can I add 18 as day to current month using java Instant

I can get the current date using
Instant.now()
I am looking to get 18-<current month>-<current year>
I endorse Basil Bourque's answer. However, if you are looking for an Instant object, you can get it by adjusting the current OffsetDateTime at UTC to 18th day of the month as shown below:
public class Main {
public static void main(String[] args) {
Instant thisInstantOn18th = OffsetDateTime.now(ZoneOffset.UTC)
.with(ChronoField.DAY_OF_MONTH, 18)
.toInstant();
System.out.println(thisInstantOn18th);
}
}
Output:
2022-12-18T19:19:20.128313Z
Learn more about the modern Date-Time API from Trail: Date Time.
tl;dr
YearMonth // Represents a year and month only, no day of month.
.now(
ZoneId.of( "America/Edmonton" ) // Returns a `ZoneId` object.
)
.atDay( 18 ) // Returns a `LocalDate` object.
.format(
DateTimeFormatter
.ofPattern( "dd-MM-uuuu" )
) // Returns a `String` object.
Details
As Comments by Ole V.V. explain, you are using the wrong class. No need for Instant here.
To represent a date, use LocalDate.
To represent a year and month, use YearMonth.
Capture the current year-month.
Doing so requires a time zone. For any given moment, the date varies around the globe by time zone. So the current month could be simultaneously “next month” in Tokyo Japan while “last month” in Toledo Ohio.
ZoneId z = ZoneId.of( "Pacific/Auckland" ) ;
YearMonth ym = YearMonth.now( z ) ;
If you want the current month as seen with an offset of zero hours-minutes-seconds from UTC, use ZoneOffset.UTC constant.
YearMonth ym = YearMonth.now( ZoneOffset.UTC ) ;
Apply a day of month to get a date.
LocalDate ld = ym.atDay( 18 ) ;
Generate text in standard ISO 8601 format.
String output = ld.toString() ;
Generate text in a specific format.
DateTimeFormatter f = DateTimeFormatter.ofPattern( "dd-MM-uuuu" ) ;
String output = ld.format( f ) ;

Create an Instance of ZonedDateTime from String with same time as String [Java]

I want to create an instance of ZonedDateTime from String. I want to make "2021-03-18 8:00:00" turn into "2021-03-18 8:00:00 EST". I don't want an unexpected variable to interfere by converting 8:00:00 to a different time from what is shown. i.e from 8:00:00 to 17:00:00.
The code that I used to try to convert it was:
SimpleDateFormat estForm = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
estForm.setTimeZone(TimeZone.getTimeZone("EST"));
String start = "2021-03-18 08:00:00";
Date estDT = estForm.parse(start);
final ZoneId zoneEST = ZoneId.of("US/Eastern");
ZonedDateTime zoneEst = ZonedDateTime.ofInstant(estDT.toInstant(), zoneEST);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
System.out.println(zoneEST);
System.out.println(zoneEst);
Here is the last output I got from this:
US/Eastern
2021-03-18T09:00-04:00[US/Eastern]
Well, you could simply do:
"2021-03-18 08:00:00" + " EST"
If you want to treat the input as a logical date-time value, parse as a LocalDateTime. This type is appropriate because your input lacks indicator of time zone or offset-from-UTC.
Then call atZone to place that date-with-time into the context of a time zone. EST is not a time zone. Such 2-4 pseudo-zones represent only a general idea of whether Daylight Saving Time (DST) is effect, and even that is just a general idea for an area, not precise. Also not standardized, and not even unique.
I will guess that you want New York time.
LocalDateTime
.parse(
"2021-03-18 08:00:00".replace( " " , "T" )
) // Returns a `LocalDateTime` object.
.atZone(
ZoneId.of( "America/New_York" )
) // Returns a `ZonedDateTime` object.
Generally best to let DateTimeFormatter automatically localize while generating text, via the `ofLocalized… methods. But if you insist on your specific method, define a formatting pattern.
DateTimeFormatter f = DateTimeFormatter.ofPattern( "uuuu-MM-dd HH:mm:ss z" ) ;
String output = zdt.format( f ) ;
Pull that code together.
ZonedDateTime zdt =
LocalDateTime
.parse( "2021-03-18 08:00:00".replace( " " , "T" ) )
.atZone(
ZoneId.of( "America/New_York" )
)
;
DateTimeFormatter f = DateTimeFormatter.ofPattern( "uuuu-MM-dd HH:mm:ss z" ) ;
String output = zdt.format( f ) ;
See this code run live at IdeOne.com.
2021-03-18 08:00:00 EDT
As we can see in that output, your desired EST is incorrect, as New York time switched off DST to standard time a few days before this date-time.

How can I get UTC Instant of startDate and endDate of today in a specific time zone ("Europe/Paris")

I want to get the UTC instant (since my DB is storing in UTC) from Java (which is also in UTC) of a particular time zone, this is what I have tried so far:
public static Instant getStartOfTheDayDateTime(Instant instant, String zoneId) {
ZonedDateTime zoned = instant.atZone(ZONE_ID_TO_ZONE_MAP.get(zoneId));
ZoneId zone = ZoneId.of(zoneId);
return zoned.toLocalDate().atStartOfDay(zone).toInstant();
// ZonedDateTime startOfTheDay = zoned.withHour(0)
// .withMinute(0)
// .withSecond(0)
// .withNano(0);
//
// return startOfTheDay.toInstant();
}
public static Instant getEndOfTheDayDateTime(Instant instant, String zoneId) {
ZonedDateTime zoned = instant.atZone(ZONE_ID_TO_ZONE_MAP.get(zoneId));
ZonedDateTime endOfTheDay = zoned.withHour(0)
.withMinute(0)
.withSecond(0)
.withNano(0)
.plusDays(1);
return endOfTheDay.toInstant();
}
Every attempt shows:
2020-04-10 22:00:00.0(Timestamp), 2020-04-11 22:00:00.0(Timestamp)
Is this the start/end of the day UTC time in Europe/Paris zone ?
I was expecting to have 2020-04-11 02:00:00.0(Timestamp), 2020-04-12 02:00:00.0(Timestamp)
Right now, Paris is on summer time: UTC+2. Paris is 'ahead' of UTC by 2 hours.
So 00:00:00 in Paris local time is 22:00:00 UTC.
Is this the start/end of the day UTC time in Europe/Paris zone ?
Yes. Europe/Paris is in daylight savings time. Midnight in Paris occurred at 22:00 UTC time.
I was expecting to have 2020-04-11 02:00:00.0(Timestamp), 2020-04-12 02:00:00.0(Timestamp)
That's not right, 02:00 UTC would have been 04:00 in Paris time.
Ask programmatically if a moment is in DST
Is this the start/end of the day UTC time in Europe/Paris zone ?
Get start of day.
ZoneId z = ZoneId.of( "Europe/Paris" );
ZonedDateTime zdtStartOfDay = instant.atZone( z ).toLocalDate().atStartOfDay( z ) ;
Ask if that moment is in DST for that zone.
ZoneRules rules = z.getRules();
boolean isDst = rules.isDaylightSavings( zdtStartOfDay.toInstant() );
Pass date-time objects rather than mere strings
public static Instant getStartOfTheDayDateTime(Instant instant, String zoneId)
I suggest you ask the calling programmer to pass a valid ZoneId object rather than a mere string. It should not be the job of this method to validate their string input. If it is reasonable to expect a Instant then it is also reasonable to expect a ZoneId.
public static Instant getStartOfTheDayDateTime(Instant instant, ZoneID zoneId )
Half-Open
public static Instant getEndOfTheDayDateTime(Instant instant, String zoneId) {
Trying to determine the last moment of the day is impossible because of infinitely divisible last second.
Also this approach to defining a span of time is awkward. It makes abutting multiple spans tricky. Various software systems and protocols differ in their resolution of that last fractional second, using milliseconds, microseconds, nanoseconds, or some other fraction.
The common practice in date-time handling is to track a span of time using the Half-Open approach. In Half-Open, the beginning is inclusive while the ending is exclusive.
So a full day begins with the first moment of the day and runs up to, but does not include, the first moment of the next day.
ZoneId z = ZoneId.of( "Europe/Paris" );
ZonedDateTime zdtStartOfDay = instant.atZone( z ).toLocalDate().atStartOfDay( z ) ;
ZonedDateTime zdtStartOfNextDay = instant.atZone( z ).toLocalDate().plusDays( 1 ).atStartOfDay( z ) ;
You might want to break that code out to more lines, for easier reading/debugging.
Instant instant = Instant.now() ; // Or passed in.
ZoneId z = ZoneId.of( "Europe/Paris" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
LocalDate ld = zdt.toLocalDate() ;
LocalDate ldNextDay = ld.plusDays( 1 ) ;
ZonedDateTime zdtStartOfNextDay = ldNextDay.atStartOfDay( z ) ;
See this code run live at IdeOne.com. For example:
System.out.println( instant ) ; // 2020-04-13T00:15:25.235341Z
System.out.println( zdt ) ; // 2020-04-13T02:15:25.235341+02:00[Europe/Paris]
System.out.println( ld ) ; // 2020-04-13
System.out.println( ldNextDay ) ; // 2020-04-14
System.out.println( zdtStartOfNextDay ) ; // 2020-04-14T00:00+02:00[Europe/Paris]
ThreeTen-Extra Interval
If you do this kind of work with spans of time often, then I suggest adding the ThreeTen-Extra library to your project. That library includes the Interval class to track a span-of-time as a a pair of Instant objects.
Interval interval = Interval.of( zdtStartOfDay.toInstant() , zdtStartOfNextDay.toInstant() ) ;
You can then make use the several handy comparison methods such as abuts, contains, encloses, intersection, overlaps, and union.
Timestamp
Never use the java.sql.Timestamp class. This class is part of the terrible date-time classes that shipped with the earliest versions of Java. These classes are now legacy, supplanted entirely by the modern java.time classes defined in JSR 310 and built into Java 8 and later.
As of JDBC 4.2 we can exchange java.time objects with a database. Use getObject and setObject and updateObject.
The JDBC spec oddly requires support for OffsetDateTime but not the more commonly used Instant and ZonedDateTime. Your particular driver may support these other types. If not, convert.
Retrieval from database.
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;
Instant instant = odt.toInstant() ;
Sending to the database.
OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC ) ;
myPreparedStatement.setObject( … , odt ) ;

Plus 1 hour and 1 day in date using java 8 apis

I have this code to add 1 hour or 1 day in date Java 8, but doesn´t work
String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
java.text.SimpleDateFormat format = new java.text.SimpleDateFormat(DATE_FORMAT);
Date parse = format.parse("2017-01-01 13:00:00");
LocalDateTime ldt = LocalDateTime.ofInstant(parse.toInstant(), ZoneId.systemDefault());
ldt.plusHours(1);
ZonedDateTime zdt = ldt.atZone(ZoneId.systemDefault());
Date te = Date.from(zdt.toInstant());
What´s wrong? The code shows: Sun Jan 01 13:00:00 BRST 2017
LocalDateTime is immutable and returns a new LocalDateTime when you call methods on it.
So you must call
ldt = ldt.plusHours(1);
Apart from the issue that you don't use the result of your date manipulation (ldt = ldt.plusHours(1)), you don't really need to go via a LocalDateTime for this operation.
I would simply use an OffsetDateTime since you don't care about time zones:
OffsetDateTime odt = parse.toInstant().atOffset(ZoneOffset.UTC);
odt = odt.plusDays(1).plusHours(1);
Date te = Date.from(odt.toInstant());
You could even stick to using Instants:
Instant input = parse.toInstant();
Date te = Date.from(input.plus(1, DAYS).plus(1, HOURS));
(with an import static java.time.temporal.ChronoUnit.*;)
tl;dr
LocalDateTime.parse( // Parse input string that lacks any indication of offset-from-UTC or time zone.
"2017-01-01 13:00:00".replace( " " , "T" ) // Convert to ISO 8601 standard format.
).atZone( // Assign a time zone to render a meaningful ZonedDateTime object, an actual point on the timeline.
ZoneId.systemDefault() // The Question uses default time zone. Beware that default can change at any moment during runtime. Better to specify an expected/desired time zone generally.
).plus(
Duration.ofDays( 1L ).plusHours( 1L ) // Add a span of time.
)
Details
Do not mix the troublesome old legacy classes Date and Calendar with the modern java.time classes. Use only java.time, avoiding the legacy classes.
The java.time classes use the ISO 8601 standard formats by default when parsing and generating strings. Convert your input string by replacing the SPACE in the middle with a T.
String input = "2017-01-01 13:00:00".replace( " " , "T" ) ;
LocalDateTime ldt = LocalDateTime.parse( input ) ;
ALocalDateTime does not represent an actual moment, not a point on the timeline. It has no real meaning until you assign a time zone.
ZoneId z = ZoneId.systemDefault() ; // I recommend specifying the desired/expected zone rather than relying on current default.
ZonedDateTime zdt = ldt.atZone( z ) ;
A Duration represents a span of time not attached to the timeline.
Duration d = Duration.ofDays( 1L ).plusHours( 1L ) ;
ZonedDateTime zdtLater = zdt.plus( d ) ;

Dates and Timezones in java

I am currently reading dates in JSON format as follows:
"dates": {
"startdate": "2017-08-29T22:00:00.000UTC";
}
And in my application, I set the JsonFormat as follows to be able to read it correctly:
#JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'UTC'")
private Date startdate;
But UTC isn't the TimeZone I want to work with, what should I change 'UTC' into to be able to read my dateTime in the Europe/Paris zone?
Alter the input to comply with the ISO 8601 standard. The Z is short for Zulu and means UTC.
String input = "2017-08-29T22:00:00.000UTC".replace( "UTC" , "Z" ) ;
Parse as an Instant object.
Instant instant = Instant.parse( input ) ;
Adjust into your desired time zone.
ZoneId z = ZoneId.of( "Europe/Paris" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
Avoid the Date class as that troublesome class is now legacy, supplanted by the java.time classes.

Categories

Resources