I'm writing a until tests to test the validity of a license key.. and at the same time, updating the code to use the java 8 java.time package.
So.. creating a 'valid until' datetime and formatting that to a string:
LocalDateTime now = LocalDateTime.now(Clock.systemUTC());
LocalDateTime nowPlus1Hour = now.plusHours(1);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss z");
formatter = formatter.withZone(Clock.systemUTC().getZone());
String validUntilString = nowPlus1Hour.format(formatter);
This.. mostly works. (My last version threw an exception because I wasn't creating a formatter 'withZone'.)
However, the value of 'validUntilString' is '2015-05-19 19:46:26 Z' Really. 'Z'. C'mon!
So.. given a LocalDateTime, how do you get a string that includes the (yes, ambigious, but in this case UTC, a standard) time zone id?
As said in the comments, the time zone is already included in your string :
"2015-05-19 19:46:26 Z"
This letter Z is coming from a military - NATO convention
The basis for this is Z – Zulu time – Zero meridian time – the same as UTC It’s a convention to assign letters to time zones, where Z= Zero meridian, and Zulu is the word that represents the letter Z, when it’s used in communication. It is sometimes used in the US Military and NATO in conjunction with 24 hour clocks, and is also popular to use in movies to reference time.
Other letters/words are used for other time zones than UTC.....
Read the cited reference for full details.
Related
The following java code throws an exception
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
simpleDateFormat.parse("2019-09-10T07:06:26.287Z")
java.text.ParseException: Unparseable date: "2019-09-10T07:06:26.287Z"
at java.text.DateFormat.parse(DateFormat.java:366)
any idea how can i fix this issue
tl;dr
Instant.parse( "2019-09-10T07:06:26.287Z" )
java.time
The modern solution uses java.time classes built into Java 8 and later, with a back-port for Java 6 & 7.
You are using their terrible predecessor classes, bundled with the earliest versions of Java. The SimpleDateFormat class and its siblings are flawed, developed by people who did not understand date-time handling. Avoid these classes entirely.
ISO 8601
Your input string represents a moment in UTC using standard ISO 8601 format. The Z on the end is short for UTC, and is pronounced “Zulu”.
The java.time classes use the standard ISO 8601 formats by default when parsing/generating strings. So no need to specify a formatting pattern.
For a moment in UTC, use the class Instant.
Instant instant = Instant.parse( "2019-09-10T07:06:26.287Z" ) ;
To see this same moment through the wall-clock time used by the people of a particular region, apply a ZoneId (time zone) to get a ZonedDateTime object.
ZoneId z = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
See this code run live at IdeOne.com.
instant.toString(): 2019-09-10T07:06:26.287Z
zdt.toString(): 2019-09-10T03:06:26.287-04:00[America/Montreal]
Same moment, same simultaneous point on the timeline, different wall-clock time.
You can also try dateparser.
It can recognize any String automatically, and parse it into Date, Calendar, LocalDateTime, OffsetDateTime correctly.
With it, you don't have to prepare any appropriate patterns like yyyy-MM-dd'T'HH:mm:ss.SSSZ:
Date date = DateParserUtils.parseDate("2019-09-10T07:06:26.287Z");
Calendar calendar = DateParserUtils.parseCalendar("2019-09-10T07:06:26.287Z");
LocalDateTime dateTime = DateParserUtils.parseDateTime("2019-09-10T07:06:26.287Z");
Please enjoy it.
I'm trying to parse this String into a ZonedDateTime:
"Mon 14 Aug 2017 02:00 AM CEST"
Here my last try:
System.out.println("Test ZonedDateTime: " + ZonedDateTime.parse(
"Mon 14 Aug 2017 02:00 AM CEST",
DateTimeFormatter.ofPattern("EEEE dd M yyyy KK:mm a z")));
And the response:
Exception in thread "main" java.time.format.DateTimeParseException: Text 'Mon 14 Aug 2017 02:00 AM CEST' could not be parsed at index 0
at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1949)
at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1851)
at java.time.ZonedDateTime.parse(ZonedDateTime.java:597)
at be.hypertux.test.localtime.Main.main(Main.java:17)
Any ideas?
One problem is that short timezone names like CEST and CET are ambiguous and not standard. The ideal is to use IANA timezones names (always in the format Continent/City, like America/Sao_Paulo or Europe/Berlin).
I'm assuming that CEST is the Central Europe Summer Time, which is used by lots of different countries (that's why it's ambiguous: you can't know which country or region it is, because it's a too broad range).
Although most abbreviations are not recognized (due to its ambiguity), some "defaults" are assumed for retro-compatibility reasons. In the version I'm using (JDK 1.8.0_131), it defaults to Europe/Paris, but not sure if that's what you need. And it's not guaranteed to work for all abbreviations. In this case, you can define a preferred timezone to be used (and that will an arbitrary choice, but there's no other way since CEST is ambiguous).
Another problem is that the month and day of week are in English (Aug and Mon), and you didn't specify a java.util.Locale. In this case, the DateTimeFormatter takes the system's default locale (and it's probably not English - check the value of Locale.getDefault()). Anyway, the default locale can be changed without notice, even at runtime, so it's better to specify one when you're dealing with localized data (like month and day of week names).
So, you must specify a locale and define an arbitrary timezone as the preferred one to be used when an ambiguous name like CEST is found. For that, you can use a java.time.format.DateTimeFormatterBuilder, a set of preferred timezones and a java.time.format.TextStyle:
// create set of preferred timezones
Set<ZoneId> zones = new HashSet<>();
// my arbitrary choice for CEST
zones.add(ZoneId.of("Europe/Brussels"));
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
// date and time
.appendPattern("EEE dd MMM yyyy hh:mm a ")
// timezone short name with custom set of preferred zones
.appendZoneText(TextStyle.SHORT, zones)
// create formatter (use English locale for month and day of week)
.toFormatter(Locale.ENGLISH);
String input = "Mon 14 Aug 2017 02:00 AM CEST";
System.out.println(ZonedDateTime.parse(input, formatter));
The output will be:
2017-08-14T02:00+02:00[Europe/Brussels]
Note that I used Europe/Brussels as the preferred timezone. You can check all the available zone names (and choose accordingly) with ZoneId.getAvailableZoneIds().
I'm using hh for the hours, which is the hour-clock-of-am-pm field (values from 1 to 12). But in your code you used KK, which is the hour-of-am-pm field (values from 0 to 11). Check which one is best for your case.
A timezone is the set of all different offsets that a region had, has and will have during its history, and the dates when Daylight Saving Time starts and ends, etc. If 2 regions had some difference in this history, they'll have different timezones (even though they use the same rules today).
Just because Paris and Brussels use the same rules today (CET and CEST), it doesn't mean it'll be like this forever (because timezones rules are defined by governments and laws and there's no guarantee that they won't be changed at any time in the future).
That's why you must define some specific timezone instead of relying on ambiguous short names (even though their use is common and widespread).
In order for your format string to work, your date would need to be formatted like so: Monday 14 8 2017 02:00 AM CEST
Take out an E and add a couple of Ms and that should do it.
Can I change the timezone of Date object in my java code without changing the date?
When I write
Date date = new Date(longValue);
I get this date in my local timezone. I want to get this date but my timezone should be one present in DB (not local) for my userID (for eg "America/Chicago").
Thanks in advance for your help.
tl;dr
ZonedDateTime zdtMontreal =
ZonedDateTime.now( ZoneId.of( "America/Montreal" ) );
ZonedDateTime zdtAuckland =
zdtMontreal.withZoneSameLocal( ZoneId.of( "Pacific/Auckland" ) );
Not the same moment. The zdtAuckland moment occurred several hours earlier.
Be certain that is truly your intention. I have a sinking feeling you are doing the wrong thing, confused about how date-time handling works. Date-time work is confusing. Be sure to search and study Stack Overflow.
java.time
The Joda-Time project, now in maintenance mode, advises migration to java.time.
The Local… classes purposely have no time zone or offset-from-UTC information.
LocalDate ld = LocalDate.of( 2016 , Month.January , 23 ); // 2016-01-23
LocalTime lt = LocalTime.of( 12 , 34 , 56 ); // 12:34:56
These values do not yet represent a point on the timeline. Would that be the noon hour of Auckland NZ, Paris FR, or Montréal CA? We must apply a time zone to determine an actual moment. We apply a ZoneId to get a ZonedDateTime.
Specify a proper time zone name in the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 3-4 letter abbreviation such as EST or IST or CST as they are not true time zones, not standardized, and not even unique(!).
ZoneId zMontreal = ZoneId.of( "America/Montreal" );
ZonedDateTime zdtMontreal = ZonedDateTime.of( ld , lt , zMontreal );
To see a string representing this value in the standard ISO 8601 format, call toString. Actually, the ZonedDateTime class extends the standard format by wisely appending the name of the time zone in square brackets.
String outputMontreal = zdtMontreal.toString();
2016-01-23T12:34:56-05:00[America/Montreal]
To get the same date and same time-of-day in another time zone, repeat the process.
ZoneId zParis = ZoneId.of( "Europe/Paris" );
ZonedDateTime zdtParis = ZonedDateTime.of( ld , lt , zParis );
ZoneId zAuckland = ZoneId.of( "Pacific/Auckland" );
ZonedDateTime zdtAuckland = ZonedDateTime.of( ld , lt , zAuckland );
But know that you are getting a different moment in time. Noon in Auckland happens several hours before noon in Paris, and noon in Montréal is even later, for three different points in time that happen to share coincidentally the same wall-clock time.
2016-01-23T12:34:56-05:00[America/Montreal]
2016-01-23T12:34:56+01:00[Europe/Paris]
2016-01-23T12:34:56+13:00[Pacific/Auckland]
Current moment
To get the current moment, call Instant.now. The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).
Instant instance = Instance.now();
Apply a ZoneId to adjust into a time zone.
ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instance.atZone( z );
Repeat the process for other desired time zones, similar to what we did further above.
As a shortcut, you can get a ZonedDateTime directly.
ZonedDateTime zdtMontreal = ZonedDateTime.now( ZoneId.of( "America/Montreal" ) );
And as another shortcut, you can apply a different time zone while retaining the same date and same time-of-day (the same wall-clock time). Call ZonedDateTime::withZoneSameLocal.
ZonedDateTime zdtAuckland = zdtMontreal.withZoneSameLocal( ZoneId.of( "Pacific/Auckland" ) );
I repeat: This results is different points on the time line. The zdtAuckland is happening several hours before zdtMontreal occurs.
To keep the same moment, instead call ZonedDateTime::withZoneSameInstant.
Database
Usually best to store your date-time values in a database in UTC. Already discussed extensively on Stack Overflow. Search for more info.
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to java.time.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
Where to obtain the java.time classes?
Java SE 8 and SE 9 and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
The ThreeTenABP project adapts ThreeTen-Backport (mentioned above) for Android specifically.
See How to use….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
You may find ZonedDateTime quite helpful:
Java 8 Convert given time and time zone to UTC time
Alternatively you can create another Date object and apply some offset to it manually.
An example of how to do it using Java8 ZonedDateTime class:
Date date = new Date(longValue);
ZoneId = ZoneId.of("America/Chicago");
ZonedDateTime dt = ZonedDateTime.ofInstant(date.toInstant(), zoneId);
You've tagged the question with Joda, but really with Java8 you don't need it anymore.
I am trying to parse a date string using the following pattern: yyMMdd and the STRICT resolver as follows:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(dateFormat).withResolverStyle(ResolverStyle.STRICT);
LocalDate.parse(expiryDate, formatter);
I get the following DateTimeParseException:
java.time.format.DateTimeParseException: Text '160501' could not be
parsed: Unable to obtain LocalDate from TemporalAccessor:
{YearOfEra=2016, MonthOfYear=5, DayOfMonth=1},ISO of type
java.time.format.Parsed
When I swith to the default resolve style, i.e. ResolverStyle.SMART it allows such dates as 30th of February.
Can someone please help?
The strict resolver requires an era to go with YearOfEra. Change your pattern to use "u" instead of "y" and it will work, ie. "uuMMdd".
While JodaStephen has nicely explained the reason for the exception and given one good solution (use uu rather than yy), I am offering a couple of other possible solutions:
The obvious one that you probably don’t want: leave the resolver style at SMART (the default). In other words either leave out .withResolverStyle(ResolverStyle.STRICT) completely or change it to .withResolverStyle(ResolverStyle.SMART).
Provide a default era.
For the second option here is a code example:
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.appendPattern("yyMMdd")
.parseDefaulting(ChronoField.ERA, 1)
.toFormatter()
.withResolverStyle(ResolverStyle.STRICT);
String expiryDate = "160501";
LocalDate result = LocalDate.parse(expiryDate, formatter);
System.out.println(result);
Output is:
2016-05-01
Where the last solution may make a difference compared to using uu in the format pattern:
It allows us to use a format pattern that is given to us where we cannot control whether pattern letter u or y is used.
With pattern letter y it will fail with an exception if the string contains a negative year. Depending on your situation and requirements this may be desirable or unacceptable.
Edit: The second argument to parseDefaulting() may also be written IsoEra.CE.getValue() rather than just 1 to make it clear that we are specifying the current era (CE; also often called Anno Domini or AD).
What's the difference between strptime and strftime? I see that strptime is a method in the DateTime class, and strftime is a method in the Time class.
What's the difference between Time and DateTime, other than that they have different core methods? The explanation for the Time class in the Ruby docs is helpful, but the one for DateTime just says "datetime". There's also the Date class, which says it provides Date and DateTime. Help me make sense of this.
I see strptime and I want to pronounce it "strip time", but that doesn't make sense. Is there a good mnemonic-device for it?
What do strptime and strftime mean, anyway?
How do you remember which does what?
The difference between Time and DateTime has to do with implementation. A large amount of the DateTime functionality comes from the Rails world and is an arbitrary date with time of day. It's more of a calendar-based system. Time is measured as seconds since January 1, 1970 UTC and is time-zone agnostic. On some systems it is limited to values between 1901 and 2038, a limitation of how traditionally this value is stored as a signed 32-bit integer, but newer versions of Ruby can handle a much wider range, using a 64-bit value or BigNum as required.
In short, DateTime is what you get from a database in Rails where Time is what Ruby has traditionally used. If you're working with values where dates are important and you want to know things like the end of the month or what day it'll be six weeks ahead, use DateTime. If you're just measuring elapsed time and don't care about that, use Time. They're easy to convert between if necessary.
Date on the other hand is just a calendar date and doesn't have any associated times. You might want to use these where times are irrelevant.
strptime is short for "parse time" where strftime is for "formatting time". That is, strptime is the opposite of strftime though they use, conveniently, the same formatting specification. I've rarely seen strptime used since DateTime.parse is usually good at picking up on what's going on, but if you really need to spell it out, by all means use the legacy parser.
strptime means string parser, this will convert a string format to datetime.
Example:-
datetime.strptime('2019-08-09 01:01:01', "%Y-%m-%d %H:%M:%S")
datetime.datetime(2019, 8, 9, 1, 1, 1)//Result
strftime means string formatter, this will format a datetime object to string format.
Example:-
sample_date=datetime.strptime('2019-08-09 01:01:01', "%Y-%m-%d %H:%M:%S")
datetime.strftime(sample_date, "%Y-%d-%m %H:%M:%S")
'2019-09-08 01:01:01'//Result
I read the above answer and it is clear in its delineation of Time, DateTime and Date in Ruby.
Time is packaged with Ruby. It is measured as seconds since January 1, 1970 UTC and is time-zone agnostic. More specifically, the Time class stores integer numbers, which presents the seconds intervals since the Epoch. We can think of this as Unix Time. It has some limitations. I read somewhere if stored as a 64-bit signed integer, it can represent dates between 1823-11-12 to 2116-02-20, but on my system it can represent dates outside this range. If you do not specify the timezone to use in the enviroment variable ENV['TZ'], then it will default to your system time found in /etc/localtime on Unix-like systems. When to use Time? It is useful for measuring time elapse or interpolating a timestamp into a string value.
Rails actually extends the Time class. It accomplishes this through ActiveSupport::TimeWithZone. It provides support for configurable time zones. Note Rails will always convert time zone to UTC before it writes to or reads from the database, no matter what time zone you set in the configuration file. In other words, it is the default behaviour of Rails that all your time will get saved into database in UTC format.
# Get current time using the time zone of current local system or ENV['TZ'] if the latter is set.
Time.now
# Get current time using the time zone of UTC
Time.now.utc
# Get the unix timestamp of current time => 1524855779
Time.now.to_i
# Convert from unix timestamp back to time form
Time.at(1524855779)
# USE Rails implementation of Time! Notice we say Time.current rather than Time.now. This will allow you to use the timezone defined in Rails configuration and get access to all the timezone goodies provided by ActiveSupport::TimeWithZone.
Time.current
TimeWithZone provides a lot of very useful helper methods:
# Get the time of n day, week, month, year ago
1.day.ago
1.week.ago
3.months.ago
1.year.ago
# Get the beginning of or end of the day, week, month ...
Time.now.beginning_of_day
30.days.ago.end_of_day
1.week.ago.end_of_month
# Convert time to unix timestamp
1.week.ago.beginning_of_day.to_i
# Convert time instance to date instance
1.month.ago.to_date
For most cases, the Time with the time zone class from Rails’ ActiveSupport is sufficient. But sometimes you just need a date.
Just as with the Time class, Ruby is packaged with the Date class. Simply require the time library:
require "time"
Time.parse("Dec 8 2015 10:19")
#=> 2015-12-08 10:19:00 -0200
Date.parse("Dec 8 2015")
#=> #<Date: 2015-12-08>
Time.new(2015, 12, 8, 10, 19)
#=> 2015-12-08 10:19:00 -0200
Date.new(2015, 12, 8)
Since Date is part of Ruby, it by default uses the timezone defined in /etc/localtime on Unix-like systems, unless you modify the TZ environmental variable. Just as with the Time class, Rails extends the Date class. Use Date.current instead of Date.today to take advantage of ActiveSupport::TimeWithZone and use Rails-based timezone configurations.
Now there is one more class available with regards to dates and times. DateTime is a subclass of Date and can easily handles date, hour, minute, second and offset. It is both available in Ruby (via require 'time') and in Rails (via require 'date'). Rails extends it with TimeZone capabilities just like with the Time class.
require 'date'
DateTime.new(2001,2,3,4,5,6)
I personally do not see a need for using DateTime in your applications, for you can use Time itself to represent dates and times, and you can use Date to represent dates.
The second part of the question was regarding strptime and strftime. Time, Date and DateTime all have the strptime and strftime methods. strptime parses the given string representation and creates an object. Here is an example:
> result = Time.strptime "04/27/2018", "%m/%d/%Y"
=> 2018-04-27 00:00:00 -0400
> result.class
=> Time
This is useful if you have an application and a user submits a form and you are given a date and/or represented as a string. You will want to parse it into a Time or Date before you save it to the database.
strftime formats a date or time. So you call it on a Date or Time object:
> Date.current.strftime("%Y-%m-%d")
=> "2018-04-27"
And you can use them together to first parse user input and then format it in a certain way, perhaps to output into a csv file:
value = Date.strptime(val, '%m/%d/%Y').strftime('%Y-%m-%d')