This question already has answers here:
Java 8 DateTimeFormatter parsing for optional fractional seconds of varying significance
(2 answers)
Closed 3 years ago.
String has to be converted to type LocalDateTime - "yyyy-MM-dd'T'HH:mm:ss".
Just ignore anything after seconds.
tried this code but errors out for anything that comes after seconds.
String testDate = "2019-09-17T23:38:47";
LocalDateTime lDate = null;
if (!StringUtils.isEmpty(testDate) && !"".equals(testDate)) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss");
try {
sqlDate = LocalDateTime.parse(testDate, formatter);
log.info("Converted SQL date=" + lDate );
} catch (Exception ex) {
log.error("Error in parsing lDate " +ex);
}
}
Try this: (+ exception handling)
String testDate = "2019-09-17T23:38:47.342";
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
java.util.Date date = format.parse(testDate);
LocalDateTime localDateTime = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
System.out.println(localDateTime);
System.out.println(localDateTime.getNano());
Output:
2019-09-17T23:38:47
0
As you can see, the fractional seconds are eliminated.
Edit:
Here's a solution with more recent date-time classes:
DateTimeFormatter format = new DateTimeFormatterBuilder()
.appendPattern("yyyy-MM-dd'T'HH:mm:ss")
.appendFraction(ChronoField.NANO_OF_SECOND, 0, 9, true)
.toFormatter();
LocalDateTime date1 = LocalDateTime.parse("2019-09-17T23:38:47", format).withNano(0);
LocalDateTime date2 = LocalDateTime.parse("2019-09-17T23:38:47.342", format).withNano(0);
System.out.println(date1);
System.out.println(date2);
Output:
2019-09-17T23:38:47
2019-09-17T23:38:47
Edit 2:
I've constructed an example for how you might deal with different types of inputs using regular expressions and format strings:
InputDatePattern.java
public enum InputDatePattern
{
WITH_TIMESTAMP("\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d{0,9})?", Optional.of("yyyy-MM-dd'T'HH:mm:ss")),
WITHOUT_TIMESTAMP("\\d{4}-\\d{2}-\\d{2}", Optional.of("yyyy-MM-dd")),
TIMESTAMP_ONLY("\\d{2}:\\d{2}:\\d{2}(\\.\\d{0,9})?", Optional.of("HH:mm:ss")),
UNKNOWN(".*", Optional.empty()); // must come last, since elements are matched in order
private final Pattern pattern;
private final Optional<DateTimeFormatter> formatter;
private static final LocalDate DEFAULT_DATE = LocalDate.EPOCH;
private static final LocalTime DEFAULT_TIME = LocalTime.MIDNIGHT;
private static final Logger log = Logger.getLogger(Logger.class.getName());
private InputDatePattern(String regex, Optional<String> format)
{
pattern = Pattern.compile(regex);
var formatter = Optional.of(new DateTimeFormatterBuilder());
formatter.ifPresent(f -> format.ifPresent(f::appendPattern));
formatter.ifPresent(f -> f.appendFraction(ChronoField.NANO_OF_SECOND, 0, 9, true));
this.formatter = formatter.map(DateTimeFormatterBuilder::toFormatter);
}
public boolean matches(String type)
{
return pattern.matcher(type).matches();
}
public Optional<LocalDateTime> toLocalDateTime(String dateString)
{
try
{
switch(this)
{
case WITH_TIMESTAMP:
return formatter.map(f -> LocalDateTime.parse(dateString, f).withNano(0));
case WITHOUT_TIMESTAMP:
return toLocalDate(dateString).map(date -> date.atTime(DEFAULT_TIME).withNano(0));
case TIMESTAMP_ONLY:
return toLocalTime(dateString).map(date -> date.atDate(DEFAULT_DATE).withNano(0));
case UNKNOWN:
return Optional.empty();
default:
throw new IllegalStateException("Attempting conversion with unknown InputDatePattern!");
}
}
catch(DateTimeParseException e)
{
log.info(e.getMessage());
return Optional.empty();
}
}
public Optional<LocalDate> toLocalDate(String dateString)
{
try
{
switch(this)
{
case WITH_TIMESTAMP:
case WITHOUT_TIMESTAMP:
return formatter.map(f -> LocalDate.parse(dateString, f));
case TIMESTAMP_ONLY:
case UNKNOWN:
return Optional.empty();
default:
throw new IllegalStateException("Attempting conversion with unknown InputDatePattern!");
}
}
catch(DateTimeParseException e)
{
log.info(e.getMessage());
return Optional.empty();
}
}
public Optional<LocalTime> toLocalTime(String dateString)
{
try
{
switch(this)
{
case WITH_TIMESTAMP:
case TIMESTAMP_ONLY:
return formatter.map(f -> LocalTime.parse(dateString, f));
case WITHOUT_TIMESTAMP:
case UNKNOWN:
return Optional.empty();
default:
throw new IllegalStateException("Attempting conversion with unknown InputDatePattern!");
}
}
catch(DateTimeParseException e)
{
log.info(e.getMessage());
return Optional.empty();
}
}
public static InputDatePattern forDateString(String dateString)
{
for(InputDatePattern pattern : InputDatePattern.values())
{
if(pattern.matches(dateString))
return pattern;
}
return InputDatePattern.UNKNOWN;
}
}
Demo.java
public class Demo
{
public static void main(String[] args)
{
String[] trying = {"2019-09-17T23:38:00", "2019-09-17T23:38:00.123",
"2019-09-17", "bad input", "09:12:13.45"};
for(String str : trying)
{
InputDatePattern pattern = InputDatePattern.forDateString(str);
System.out.format("Input pattern type for %s is %s%n", str, pattern);
Optional<LocalDateTime> localDateTime = pattern.toLocalDateTime(str);
if(localDateTime.isPresent())
{
System.out.println("The corresponding LocalDateTime is: "+localDateTime.get());
}
else
{
System.out.format("Unknown type of LocalDateTime! Bad input=\"%s\"%n",str);
}
}
}
}
Output:
Input pattern type for 2019-09-17T23:38:00 is WITH_TIMESTAMP
The corresponding LocalDateTime is: 2019-09-17T23:38
Input pattern type for 2019-09-17T23:38:00.123 is WITH_TIMESTAMP
The corresponding LocalDateTime is: 2019-09-17T23:38
Input pattern type for 2019-09-17 is WITHOUT_TIMESTAMP
The corresponding LocalDateTime is: 2019-09-17T00:00
Input pattern type for bad input is UNKNOWN
Unknown type of LocalDateTime! Bad input="bad input"
Input pattern type for 09:12:13.45 is TIMESTAMP_ONLY
The corresponding LocalDateTime is: 1970-01-01T09:12:13
Related
I have a code that supports only API Level >= 26 in android:
public static String in = "7:00:00";
public static String in_until = "11:50:00";
public static String breakout_out = "11:51:00";
public static String breakout_out_until = "12:50:00";
public static String breakout_in = "12:51:00";
public static String breakout_in_until = "13:10:00";
public static String out = "16:50";
public static String getCurrentTimeLogType() {
// LocalTime target = LocalTime.parse( DataHandler.timestamp().split(" ")[1] ) ;
LocalTime target = LocalTime.parse("7:30:00") ;
if (target.isBefore(in) || (target.isAfter(in) && target.isBefore(in_until)))
return "TIME-IN";
else if (target.isAfter(breakout_out) && target.isBefore(breakout_out_until))
return "BREAK-OUT";
else if (target.isAfter(breakout_in) && target.isBefore(breakout_in_until))
return "BREAK IN";
else if (target.isAfter(out))
return "TIME-OUT";
return "UNKNOWN!";
}
I want to return if the specified time in the variables is within the current time to return what type of timestamp to add to database.
For example if today is 12:05 PM:
if (12:05 >= breakout_out && 12:05 <= breakout_out_until)
return "BREAK-OUT"
I want to achieve something like this. How can I achieve a code like this without using the unsupported LocalTime module?
What about something like below. Not tested though.
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
Date breakout_out = sdf.parse("11:51:00");
Date breakout_out_until = sdf.parse("13:10:00");
Date current_time = sdf.parse("12.05.00");
if(current_time.before(breakout_out_until) && current_time.after(breakout_out)) {
return "BREAK-OUT"
}
how to use java in xslt and avoid below errors:
Cannot find a 1-argument function named
{java:com.poc.XSDDateTimeFormatter}toXSD(). Reflexive calls to Java
methods are not available under Saxon-HE and Cannot find a 2-argument
function named
{urn:java:com.poc.NLDataUnitTestTimeCalc}computeTestTime(). Reflexive
calls to Java methods are not available under Saxon-HE
computeTestTime method of NLDataUnitTestTimeCalc class
public static long computeTestTime( String startDateStr, String endDateStr) {
long testTime= 0;
long longStartDate= 0;
long longEndDate= 0;
for( String format: formats) {
try {
SimpleDateFormat formatter = new SimpleDateFormat(format);
Date startdate = formatter.parse(startDateStr);
Date enddate = formatter.parse(endDateStr);
longStartDate=startdate.getTime();
longEndDate=enddate.getTime();
testTime = (Math.abs(longEndDate-longStartDate)/1000);
break;
}
catch (ParseException ex) {
//ignore
}
}
return testTime;
}
toXSD method of XSDDateTimeFormatter class
public static String toXSD( String dateStr) {
for( String format: formats) {
try {
Date date = new SimpleDateFormat( format).parse( dateStr);
String xsd = new SimpleDateFormat( XSDdateTimeFormat).format( date);
//special case for xsd:dateTime timezone format
return
xsd.substring(0, xsd.length() - 2) +
':' +
xsd.substring(xsd.length() - 2);
} catch (ParseException ex) {
//ignore
}
}
return dateStr; }
xslt
<xsl:template match="/Event">
<bus:Timestamp>
<xsl:value-of xmlns:XSDDateTimeFormatter="java:com.amd.pde.integration.XSDDateTimeFormatter"
select="XSDDateTimeFormatter:toXSD( //TimeStamp)"
/>
</bus:Timestamp>
sample xml
<Event>
<Message>BEGINEXECUTION</Message>
<TimeStamp>20080111000419146</TimeStamp>
<EquipmentID>stack</EquipmentID>
</Event>
As the error message says, you use Saxon-HE, but extension functions in Java are only supported by Saxon-PE and Saxon-EE. The Saxon-Docs mention this explicitly.
I guess you have two options
Buy Saxon-PE or Saxon-EE
Implement your functions in XSL
I have below method in which different date patterns have been handled
below is the method in which different date formats have been handled now
now for the particulat format YYYY-MM-dd i don't want it to go for the check where we are prefixing 20 before in code please advise how can i skip that part lets say if the date pattern is YYYY-MM-dd then avoid the logic of prefixing 20 in front of year
below is my code
public java.util.Date extractDate(String dateStr, String dateType) {
String[] datePatternsOfUk = { "d-M-yy", "d-M-yyyy", "d/M/yy", "d/M/yyyy", "yyyy-MM-dd","dd-MM-yy", "dd-MMM-yy","dd-MMM-yyyy","dd-MM-yyyy",
"dd/MM/yy","dd/MMM/yy","dd/MMM/yyyy"};
String[] datePatternsOfUs = { "M-d-yy","MM-dd-yy","M/d/yy","MM/dd/yy", "MM/dd/yy", "MMM-dd-yy",
"MMM/dd/yy", "MMM-dd-yyyy", "MM-dd-yyyy", "MMM/dd/yyyy",
"MM/dd/yyyy" };
java.util.Date date = null;
String[] datePatterns = datePatternsOfUk;
if (dateType.equals("US")) {
datePatterns = datePatternsOfUs;
} else if (dateType.equals("UK")) {
datePatterns = datePatternsOfUk;
}
///******code should not go in this check where date pattern is YYYY-MM-dd
int p = dateStr.lastIndexOf("/");
if (p == -1) {
p = dateStr.lastIndexOf("-");
}
String firstSubstring = dateStr.substring(0, p + 1);
String secondSubstring = dateStr.substring(p + 1);
if (p != -1 && secondSubstring.length() <= 2) {
secondSubstring = Integer.toString(2000 + Integer.parseInt(secondSubstring));
dateStr = firstSubstring + secondSubstring;
}
///****************************************//
try {
date = DateUtils.parseDate(dateStr, datePatterns);
} catch (ParseException ex) {
logger.error("##$$$$$### Error in invoice inside extractDate method : ##$$$$$$#### "
+ ErrorUtility.getStackTraceForException(ex));
}
return date;
}
You could avoid trying any inappropriate pattern by checking if the string "looks like" the pattern before parsing with the pattern.
The general way to do this is:
String datePattern = "yyyy-MM-dd"; // for example
String input;
if (input.matches(datePattern.replaceAll("\\w", "\\d"))) {
// the input looks like the pattern
// in this example "dddd-dd-dd" where "d" is any digit
// so go ahead and try the parse
}
You can enhance this logic to add:
if (input.matches("\\d\\d\\D.*")) {
// then it only has a two digit year, so add "20" to the front
}
if (!dateStr.equals("YYYY-MM-dd")) {
// code
}
I am writing a credit card program. I want the program to use the current date every time the method is used to make a purchase and put the date into the array
private GregorianCalendar transDate;
public CreditCard(double amount,String storeName, GregorianCalendar transDate) {
this.amount=amount;
this.storeName=storeName;
transDate=new GregorianCalendar();
}
public void purchase(double amount, String storeName, GregorianCalendar date)throws Exception
{
if (numPurchases<purchases.length)
if (amount >0 )
if(amount+balance<=creditLimit)
if( GregorianCalendar.getInstance().getTimeInMillis()<=expDate.getTimeInMillis())
{
balance+=amount;
transDate=getTransDate();
purchases[numPurchases] = new CreditCard(amount, storeName,transDate);
numPurchases++;
}
else
{
throw new Exception("card expired");
}
else{
throw new Exception("insufficient credit");
}
else{
throw new Exception("invalid amount");
}
else{
throw new Exception("exceeded number of allowed purchases");
}
}
I would like to display the information in String info
info+="Purchases:\n";
for(int index=0;index<numPurchases;index++){
info+="["+(index+1)+"] ";
info+=transDate.get(Calendar.YEAR)+"\t";
info+= purchases[index].getStoreName()+"\t";
info+=(formatter.format(purchases[index].getPurchase()))+"\n" ;
}
how do I need to set up the code to use the current date and add it to the array and display it in the string
Why don't you use a List implementation instead of an array? You can override the toString method to print it the way you want.
final SimpleDateFormat formatter = new SimpleDateFormat("dd MM yyyy");
List<Calendar> dates = new ArrayList<Calendar>() {
private static final long serialVersionUID = -5079502477457556887L;
#Override
public String toString() {
Iterator<Calendar> i = iterator();
if (!i.hasNext())
return "[]";
StringBuilder sb = new StringBuilder();
sb.append('[');
for (;;) {
Calendar c = i.next();
sb.append(formatter.format(c.getTime()));
if (! i.hasNext())
return sb.append(']').toString();
sb.append(", ");
}
}
};
dates.add(Calendar.getInstance());
dates.add(Calendar.getInstance());
System.out.println(dates);
What does your getTransDate() function do? Ideally it should return the transDate variable of CreditCard object. To calculate transDate for a purchase, you are better off renaming the method to calculateTransDate() or something like that.
Once you have getTransDate() method returning the transDate, your info string can be :
info+="Purchases:\n";
for(int index=0;index<numPurchases;index++){
info+="["+(index+1)+"] ";
info+=purchases[index].getTransDate().get(Calendar.YEAR)+"\t";
info+= purchases[index].getStoreName()+"\t";
info+=(formatter.format(purchases[index].getPurchase()))+"\n"
}
I am parsing several documments with the field Duration. But in the differents files, it is in differnt formats, ex:
"Duration": "00:43"
"Duration": "113.046"
"Duration": "21.55 s"
I want to parse all of them to the format "Duration": "113.046", how could I check before any parsing in wich format it is??
Some conditions before this piece of code, because this is not right for all of them:
Long duration;
DateFormat sdf = new SimpleDateFormat("hh:mm:ss");
try {
Date durationD = sdf.parse(totalDuration);
Date zeroSec = sdf.parse("00:00:00");
duration = durationD.getTime() - zeroSec.getTime();
} catch (Exception e) {
duration = Long.parseLong(totalDuration);
}
Thanks in advance
You could match the pattern with help of regex and then format accordingly. Here's a kickoff example:
Map<Pattern, DateFormat> dateFormatPatterns = new HashMap<Pattern, DateFormat>();
dateFormatPatterns.put(Pattern.compile("\\d{1,2}:\\d{2}"), new SimpleDateFormat("H:m"));
dateFormatPatterns.put(Pattern.compile("\\d{1,3}\\.\\d{3}"), new SimpleDateFormat("s.S"));
dateFormatPatterns.put(Pattern.compile("\\d{1,2}\\.\\d{2} s"), new SimpleDateFormat("s.S 's'"));
String[] strings = { "00:43", "113.046", "21.55 s" };
DateFormat finalFormat = new SimpleDateFormat("HH:mm:ss");
for (String string : strings) {
for (Pattern pattern : dateFormatPatterns.keySet()) {
if (pattern.matcher(string).matches()) {
Date date = dateFormatPatterns.get(pattern).parse(string);
String formattedTime = finalFormat.format(date);
System.out.println(formattedTime);
break;
}
}
}
This yields here
00:43:00
00:01:53
00:00:21
If these are all your known input formats, then convert your input to your expected date format.
Just string-replace all : with . and remove s.
Do not forget to strip the spaces, too. By the way, "113.046" seems a bit odd date format to me - if I were in your shoes, I would have used some of the standard date time formats and convert the irregular ones.
My solution, not smart at all:
long DurationFixer(String duration){
long durationLong = 0;
if(duration.contains(":")){
DateFormat sdf = new SimpleDateFormat("mm:ss");
try {
Date durationD = sdf.parse(duration);
Date zeroSec = sdf.parse("00:00:00");
durationLong = durationD.getTime() - zeroSec.getTime();
} catch (Exception e) {
durationLong = (Long.parseLong(duration))/1000;
}
}
else{
String r = "";
if(duration.contains("s")){
for (int i = 0; i < duration.length()-2; i ++) {
if ((duration.charAt(i) == '.'))
break;
else
r += duration.charAt(i);
}
}
durationLong = Long.valueOf(r);
}
return durationLong;
}
If someone could find a better solution, please, tell me.
Thanks everybody!