I am pulling 2 time values (as strings) from an XML file using xpath, these values (for example) are as follows:
00:07
08:00
00:07 is equal to 7 minutes
08:00 means 8am, with no date associated or needed (that is handled elsewhere)
Each of these values is subject to change in each XML file that i read. What i am attempting to do is as follows:
I need to subtract or add (depending on the situation) the 7mins from the 8am and give me a hh:mm time (eg: 07:53 or 08:07) in a string that i can eventually output to CSV
Next i need to produce 2 additional strings, 1 min before and 1 min after (eg: 07:52 and 07:54 OR 08:06 and 08:08) which also need to be output to CSV
I have tried everything and i can think of in relation to the time interpretation and manipulation to get the minutes subtracted/added to the time and then +/- 1 min from there, but being a complete novice i am totally stuck despite reading and testing as much as i could find. Spent the last 2 days working with Joda Time for the first time but i must be missing something fundamental as i cannot get the desired result with this either.
The question is - how can i achieve this?
Some sample code that gets me reading from the XML and printing the time
FileInputStream file = null;
try {
file = new FileInputStream(new File("Output/XmlConfig.xml"));
} catch (FileNotFoundException ex) {
Logger.getLogger(KATT.class.getName()).log(Level.SEVERE, null, ex);
}
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = null;
try {
builder = builderFactory.newDocumentBuilder();
} catch (ParserConfigurationException ex) {
Logger.getLogger(KATT.class.getName()).log(Level.SEVERE, null, ex);
}
Document xmlDocument = null;
try {
xmlDocument = builder.parse(file);
} catch (SAXException ex) {
Logger.getLogger(KATT.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(KATT.class.getName()).log(Level.SEVERE, null, ex);
}
XPath xPath = XPathFactory.newInstance().newXPath();
//get In Early rule from XML
String exceptionInEarlyXML = "Root/Response/WSAExceptionRule/#InEarly";
NodeList nodeListInEarly = null;
try {
nodeListInEarly = (NodeList) xPath.compile(exceptionInEarlyXML).evaluate(xmlDocument, XPathConstants.NODESET);
} catch (XPathExpressionException ex) {
Logger.getLogger(KATT.class.getName()).log(Level.SEVERE, null, ex);
}
String exceptionInEarly = (nodeListInEarly.item(1).getFirstChild().getNodeValue());
String InEarly = exceptionInEarly;
SimpleDateFormat format = new SimpleDateFormat("hh:mm");
Date d2 = null;
try {
d2 = format.parse(InEarly);
} catch (ParseException ex) {
Logger.getLogger(KATT.class.getName()).log(Level.SEVERE, null, ex);
}
DateTime dt2 = new DateTime(d2);
System.out.println(dt2);
This give me an output of 1970-01-01T00:07:00.000+10:00
I have tried so many permutations of code that i am at the point of deleting and starting again from scratch as it is un-compilable, and i am not experienced enough yet to be able to solve this issue.
Once you have the Date object for the parsed time, use getTime() to get the time in milliseconds and save it into a long variables. Then parse the offset time format and use a NumberFormat to get the number of minutes to offset. Add or subtract as needed. Take the result and create a new Date(millis) then apply your format to it.
Here is a working example:
String sTime = "08:00";
String sOffset ="00:07";
SimpleDateFormat dateFormat = new SimpleDateFormat("hh:mm");
Date dtTime = null;
try {
dtTime = dateFormat.parse(sTime);
} catch (ParseException e) {
// handle exception
return;
}
String[] offsetHrsMins = null;
NumberFormat numberFormat = NumberFormat.getNumberInstance();
long offsetMillis = 0;
try {
offsetHrsMins = sOffset.split(":");
long offsetHrs = (Long) numberFormat.parse(offsetHrsMins[0]);
long offsetMins = (Long) numberFormat.parse(offsetHrsMins[1]);
offsetMillis = 1000 * 60 * ((offsetHrs * 60) + offsetMins);
} catch (ParseException e) {
// handle exception
return;
}
long lTime = dtTime.getTime();
System.out.println("Adding minutes: " + dateFormat.format(new Date(lTime + offsetMillis)));
System.out.println("Subtracting minutes: " + dateFormat.format(new Date(lTime - offsetMillis)));
output:
Adding minutes: 08:07
Subtracting minutes: 07:53
First, you need to use SimpleDateFormat to parse the Date String to a Java.util.Date Object.
Second, After getting the Date Object, you can easily add/substract some time, and get another Date Object.
Last, you can use another SimpleDateFormat object to format the Date Object you got in second step to String.
SimpleDateFormat is very useful in Processing Date Strings. You can refer to the Javadoc in JDK or search some examples by Google.
Try passing the strings into a method aswel as what you are subrtacting by
Then converting them to ints
Then have an if statment that if the subtraction amount is greater that the minets int
then it subtracts 1 from the hours int and sets the new minets int to 60 subtract the subtraction int
Then convert them back to Strings
Here is the code exept for turing it back into a string
public class Main {
static String hours="8";
static String minets="7";
static String minus="17";
public static void main(String[] args) {
Main m = new Main();
m.timechange(hours,minets,minus);
}
void timechange(String hour, String minuet, String subtract){
int h = Integer.parseInt(hour);
int m = Integer.parseInt(minuet);
int s = Integer.parseInt(subtract);
if(s>m){
h-=1;
m=60-s;
}
else{
m-=s;
}
if ((m>9)&&(h>9)) {
System.out.println(h+":"+m);
} else {if ((m<10)&&(h<10)) {
System.out.println("0"+h+":0"+m);
}else {if ((m<10)&&(h>9)) {
System.out.println(h+":0"+m);
}else {if ((m>9)&&(h<10)) {
System.out.println("0"+h+":"+m);
}
}
}
}
}}
I wasnt sure if you wanted the back to String.
Hopeful that answers your question
The same can be done for when the minets reach over 60 if that ever happens.
Here a genuine Joda-Time answer because OP wants Joda-Time (and I also consider that library as superior to java.util.Date, java.text.SimpleDateFormat etc.):
Joda-Time has the big advantage of having several different temporal types. The right type for handling plain wall times is LocalTime. It also defines a method to add minutes.
Your task:
I need to subtract or add (depending on the situation) the 7mins from the 8am and give me a hh:mm time (eg: 07:53 or 08:07) in a string that i can eventually output to CSV
Next i need to produce 2 additional strings, 1 min before and 1 min after (eg: 07:52 and 07:54 OR 08:06 and 08:08) which also need to be output to CSV
The solution (only for part one, the other part is very similar):
LocalTime time = new LocalTime(8, 0); // corresponds to 08:00
LocalTime laterBy8Minutes = time.plusMinutes(7);
LocalTime earlierBy8Minutes = time.minusMinutes(7);
String sLaterBy8Minutes = laterBy8Minutes.toString("HH:mm"); // 08:07
String sEarlierBy8Minutes = earlierBy8Minutes.toString("HH:mm"); // 07:53
One additional note: If you start with another type like java.util.Date and wish to convert it to LocalTime then you can use the constructor
new LocalTime(jdkDate, DateTimeZone.forID("Europe/Moscow")) // example
or for default timezone:
new LocalTime(jdkDate)
Related
I'm new to java and I got this assignment to make a timer app with two options, "on time" and countdown" In both cases an app has to open a new window where colors are changing. I'm having problem with first option, for some reason I cant parse time to formatted text field.
I have tried several methods, sometimes it crashes and sometime it just starts working regardless of given time.
{
if (jCheckBox1.isSelected()){
st=true;
Object set = jFormatted.getText();
String setTime = new SimpleDateFormat("HH:mm:ss").format(set);
String appTime1 = new SimpleDateFormat("HH:mm:ss").format(appTime);
try
SimpleDateFormat form = new SimpleDateFormat("HH:mm:ss");
Date d1 = form.parse(setTime);
Date d2 = form.parse(appTime1);
razlika = d1.getTime() - d2.getTime();
catch (Exception e) {
JOptionPane.showMessageDialog(null, e.getMessage());
}
This question already has answers here:
SimpleDateFormat.parse() ignores the number of characters in pattern
(5 answers)
Closed 7 years ago.
I am working on a project where I need to validate multiple dates based on length and patterns. I am using simple date format and found many issues with that. My requirement is to strictly allow if date string matches "yyyy/MM/dd" and strictly 10 characters.
The below code is not giving expected results for various testing input strings.
public static boolean checkformat(String dateString){
boolean flag = false;
Date d1 = null;
SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd");
format.setLenient(false);
try {
d1 = format.parse(dateString);
flag=true;
} catch (ParseException ex) {
ex.printStackTrace();
return false;
}
return flag;
}
the above code is returning "true" for various inputs like "99/03/1" (should be 0099/03/01) and 99/1/1( should be 0099/01/1). Since the input strings are not coming from a from so I cant perform validations before passing them to this method. Please suggest any implementation which should act very strict towards the dateformat("yyyy/MM/dd").
I suggest that you should try to validate date with regex before format it.
user below code for validate
public static boolean checkformat(String dateString){
boolean flag = false;
Date d1 = null;
SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd");
format.setLenient(false);
try {
if (dateString.matches("([0-9]{4})/([0-9]{2})/([0-9]{2})")) { // use this regex
d1 = format.parse(dateString);
flag=true;
}
} catch (ParseException ex) {
ex.printStackTrace();
return false;
}
return flag;
}
Okay, first: You know what format you're expection. So why just parse it and catch an exception rather than checking preconditions ?
if(dateString.size() > 10) {
...
What you are actually doing is not checking your input format but rather parsing it - though the method is not expressing this contract -
so if your method is just for checking you could:
1. Use a regex
2. ... ?
I know that are quiet a lot of answers on the net which propose using SimpleDateFormat, but - to be frank -they are wrong.
If I am expecting a given format, e.g. as I know that conversions have been made on some user input, I can start parsing a string, and considering that something may have gone wrong, catch the exception. If I don't know which format is passed to me, I am at the validation layer and this layer should not try to perform a conversion but rather proof that the conversion would be valid.
You could try using the new java.time package from Java 8 and later. You could use it as so to replace the SimpleDateFormat:
public static boolean checkformat(String dateString){
boolean flag = false;
try {
TemporalAccessor ta = DateTimeFormatter.ofPattern("yyyyMMdd").parse(strDate);
flag=true;
} catch (DateTimeParseException ex) {
ex.printStackTrace();
return false;
}
return flag;
}
This would also limit the values from making no sense (e.g. month value being 18).
String[] removeSlashes=new String[3];
removeSlashes = enteredDate.split("/");
if(removeSlashes[0].length()!=4)
throw new IncorrectDateFormatException(); // user defined exception
if(removeSlashes[1].length()!=2)
throw new IncorrectDateFormatException();
if(removeSlashes[2].length()!=2)
throw new IncorrectDateFormatException();
//Then use SimpleDateFormat to verify
I am trying to change the account expiration date in windows active directory.
I can able to change the Never option in account expiry using the below code .
final Modification mod = new Modification(ModificationType.REPLACE,
"accountExpires", "9223372036854775807");//Can change the required date with milliseconds
LDAPResult result=connection.modify(userDN, mod);
But , If I tried to change the account expiry date means , the code executed successfully and success was printed in console . But the date is not changed in the AD.
Here is my code to change or extend the account expiry date.
public class AccountExpireSetting {
public void ChangeAccountExpires(String userDN,String password , String dateToChange) throws LDAPException
{
LDAPConnection connection=null;
String someDate = null;
try {
connection = new LDAPConnectionObject().getConnection();
} catch (LDAPException e1) {
e1.printStackTrace();
}
try{
SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy");
Date date = sdf.parse(dateToChange);
System.out.println("Date to MillSeconds : "+date.getTime());
someDate = String.valueOf(date.getTime());
Date date1=new Date(date.getTime());
System.out.println("MillSeconds to Date : "+date1);
}
catch(Exception e){
e.printStackTrace();
}
try{
System.out.println("Going to replace account expires to never");
final Modification mod = new Modification(ModificationType.REPLACE,
"accountExpires", someDate);// 9223372036854775807 milliseconds can change the password to never expire
// 9223372036854775807
LDAPResult result=connection.modify(userDN, mod);
System.out.println("Account expires status : " + result); // Password status : LDAPResult(resultCode=0 (success), messageID=2, opType='modify')
}catch(LDAPException e) {
// TODO Auto-generated catch block
System.out.println("Error in replacing account expires to never");
e.printStackTrace();
}finally
{
System.out.println("Closing the connection.");
connection.close();
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
String temp="CN=Anand,OU=Java,OU=Chennai,OU=Department,dc=tstdmn,dc=com";
try {
new AccountExpireSetting().ChangeAccountExpires(temp, "password#123","08.06.2014");
} catch (LDAPException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Hope you people will give a better solution.
The acountExpires is not milliseconds but rather the number of 100 nanosecond intervals since January 1, 1601 (UTC).
If a user object in Active Directory has never had an expiration date, the accountExpires attribute is set to a huge number. The actual value is 2^63 – 1, or 9,223,372,036,854,775,807. This is because 64-bit numbers can range from -2^63 to 2^63 - 1, making this the largest number that can be saved as a 64-bit value. Obviously this represents a date so far in the future that it cannot be interpreted. In fact, AccountExpirationDate raises an error if it attempts to read this value. If a user object has an expiration date, and then you remove this date in ADUC by selecting "Never" on the "Account" tab, the GUI sets accountExpires to 0. Thus, the values 0 and 2^63 - 1 both really mean "Never"
For one way to change in Java try looking at this discussion.
-jim
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I have a table in which I've assigned burst time for each of machines in the form of time type in second for eg: 00:00:03, 00:00:02 etc.
I have a JAVA code that retrieves these burst times from the database and store it in a list and then convert each burst time into "milliseconds" type.
ArrayList<String>list22=new ArrayList<String>();
ResultSet rs = stmt1
.executeQuery("SELECT burst_time FROM virtual_machine WHERE VM_id <= 4");
while (rs.next()) {
list22.add(rs.getString("burst_time"));
}
String tempStamp = list22.get(0);
int i;
for(i=0;i<=list22.size()-1;i++){
System.out.println(list22.get(i));
}
for(String startstamp : list22){
SimpleDateFormat formatter = new SimpleDateFormat("HH:mm:ss");
formatter.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));
java.util.Date d = null;
try
{
d = formatter.parse(startstamp);}
catch (java.text.ParseException e) {
System.err.println("Error: " + e.getMessage());
}
long qtm= d.getTime();
System.out.println(qtm);
}
This gives me the following result:
00:00:03
00:00:02
00:00:02
00:00:03
3000
2000
2000
3000
Now I need to store those milliseconds values in an array bur[] and use it in the program so that the corresponding machines should run for the assigned time which is stored in the array.
And can u please tell me whether I'm going through the right path in case of storing the milliseconds in array and giving it to the machines.
Following solution is nearly identical to the answer of #nikis, but preserves the important timezone setting. Otherwise users will get a surprising experience if this code runs in UK (Europe/London) because in year 1970 there was summer time - resulting in duration longs with one full hour too much:
long[] bur = new long[list22.size()];
for(int i=0; i < list22.size(); i++) {
SimpleDateFormat formatter = new SimpleDateFormat("HH:mm:ss");
// important, but avoid deprecated Etc/GMT-notation
formatter.setTimeZone(TimeZone.getTimeZone("GMT"));
try
{
java.util.Date d = formatter.parse(list22.get(i));
long qtm= d.getTime();
bur[i] = qtm;
System.out.println(qtm);
} catch (java.text.ParseException e) {
System.err.println("Error: " + e.getMessage());
}
}
Hereby I have presented a workaround for an unsupported handling of durations in JDK pre 8. The truth is that SimpleDateFormat is designed to parse points in time, but not durations. Therefore it is so important to have a fixed starting point which never changes, hence the choice of UTC time zone and the reference point 1970-01-01T00:00:00,000Z (elapsed milliseconds since UNIX epoch).
JodaTime offers a specialized PeriodFormatter which really yields a org.joda.time.Period. Else it is possible to write your own specialized string parser (by help of substring(), indexOf() etc.) to factor out the integer parts and then to use Integer.valueOf(String) and then to calculate a long using this simple formula: (hour * 3600 + minute * 60 + second) * 1000.
I've modified your code to avoid NPE and also added bur[] array:
ArrayList<String>list22=new ArrayList<String>();
ResultSet rs = stmt1
.executeQuery("SELECT burst_time FROM virtual_machine WHERE VM_id <= 4");
while (rs.next()) {
list22.add(rs.getString("burst_time"));
}
for(int i=0;i<list22.size();i++){
System.out.println(list22.get(i));
}
long[] bur = new long[list22.size()];
for(int i=0;i<list22.size();i++){
SimpleDateFormat formatter = new SimpleDateFormat("HH:mm:ss");
try
{
java.util.Date d = formatter.parse(list22.get(i));
long qtm= d.getTime();
bur[i] = qtm;
System.out.println(qtm);
} catch (java.text.ParseException e) {
System.err.println("Error: " + e.getMessage());
}
}
Try this:
int bur[] = new int[list22.size()];
for(int i = 0; i < list22.size(); i++) {
String timeStamp = list22.get(i);
String s, m, h, split;
split = timeStamp.split(":");
h = split[0];
m = split[1];
s = split[2];
bur[i] = Integer.parseInt(s) * 1000 + Integer.parseInt(m) * 60000 + Integer.parseInt(h) * 3600000;
}
This solution doesn't use any date objects, since you won't need them in your case, if I'm not totally on the wrong way ;-)
I have an ArrayList including several number of time-stamps and the aim is finding the difference of the first and the last elements of the ArrayList.
String a = ArrayList.get(0);
String b = ArrayList.get(ArrayList.size()-1);
long diff = b.getTime() - a.getTime();
I also converted the types to int but still it gives me an error The method getTime is undefined for the type String.
Additional info :
I have a class A which includes
String timeStamp = new SimpleDateFormat("ss S").format(new Date());
and there is a class B which has a method private void dialogDuration(String timeStamp)
and dialogueDuration method includes:
String a = timeSt.get(0); // timeSt is an ArrayList which includes all the timeStamps
String b = timeSt.get(timeSt.size()-1); // This method aims finding the difference of the first and the last elements(timestamps) of the ArrayList (in seconds)
long i = Long.parseLong(a);
long j = Long.parseLong(b);
long diff = j.getTime()- i.getTime();
System.out.println("a: " +i);
System.out.println("b: " +j);
And one condition is that the statement(String timeStamp = new SimpleDateFormat("ss S").format(new Date());) wont be changed in class A. And an object of class B is created in class A so that it invokes the dialogueDuration(timeStamp) method and passes the values of time-stamps to class B.
My problem is this subtraction does not work, it gives an error cannot invoke getTime() method on the primitive type long. It gives the same kind of error also for int and String types?
Thanks a lot in advance!
Maybe like this:
SimpleDateFormat dateFormat = new SimpleDateFormat("ss S");
Date firstParsedDate = dateFormat.parse(a);
Date secondParsedDate = dateFormat.parse(b);
long diff = secondParsedDate.getTime() - firstParsedDate.getTime();
Assuming you have Timestamp objects or Date Objects in your ArrayList you could do:
Timestamp a = timeSt.get(0);
Timestamp b = timeSt.get(timeSt.size()-1);
long diff = b.getTime() - a.getTime();
You can calculate the difference with the both following methods(also you can modify the mentioned methods to return difference as 'millisecond', 'day', 'month', etc by adding additional if statement or using switch case):
private Long calculateDifference(String date1, String date2, String value) {
Timestamp date_1 = stringToTimestamp(date1);
Timestamp date_2 = stringToTimestamp(date2);
long milliseconds = date_1.getTime() - date_2.getTime();
if (value.equals("second"))
return milliseconds / 1000;
if (value.equals("minute"))
return milliseconds / 1000 / 60;
if (value.equals("hours"))
return milliseconds / 1000 / 3600;
else
return new Long(999999999);
}
private Timestamp stringToTimestamp(String date) {
try {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date parsedDate = dateFormat.parse(date);
return new Timestamp(parsedDate.getTime());
} catch (Exception e) {
return null;
}
}
For example:
calculateDifference("2021-10-20 10:00:01", "2021-10-20 10:15:01", "minute");
will return '-15'
or
calculateDifference("2021-10-20 12:00:01", "2021-10-20 10:15:01", "minute");
will return '105'
You should make your ArrayList x to an ArrayList<TimeStamp> x. Subsequently, your method get(int) will return an object of type TimeStamp (instead of a type String). On a TimeStamp you are allowed to invoke getTime().
By the way, do you really need java.sql.TimeStamp? Maybe a simple Date or Calendar is easier and more appropriate.