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 ;-)
Related
As a followup to a comment on my question at Is this query that tries to get timeseries statuses with truncated dates even possible in regular relational databases? I have implemented a timeseries query on postgres that works reasonably well. It flattens time on whole periods (like days) and joins it with some data.
There is a major problem with it though: the query is timezone-dependent which works fine, but when a Daylight Savings Time (DST) happens in the middle of the generated series, this is not reflected in the output. In some timezones it unfortunately is the case that 1 day in the year takes only 23 hours and another day takes 25 hours. I need the data to be aggregated on this 23 or 25 hour period, because those are true calendar days in that timezone. But with the current query it just always adds 1 day to the series. This means that during a DST switch, I get output with data like:
date 1: 00:00
date 2: 00:00
date 3: 00:00
(now a DST change happens)
date 3: 23:00
date 4: 23:00
... and so on
I'm at a loss on how to rewrite this query to take into account that certain days take less or more hours in some timezones. Because the generate_series is based on intervals. Any ideas? The actual code has an arbitrary period and amount btw, it could also be 5 months or 3 hours.
Here's the full query, though I imagine only the sub1 query is relevant.
SELECT sub2.fromdate,
sub2.eventlevel,
sub2.count
FROM
(SELECT sub1.fromdate AS fromdate,
sub1.maxeventlevel AS eventlevel,
count(*) AS COUNT
FROM
(SELECT e.subject_id,
MAX(e.event_level) AS maxeventlevel,
d.date AS fromdate
FROM
(SELECT generate_series(date_trunc(?, ? AT TIME ZONE ?) AT TIME ZONE ?, date_trunc(?, ? AT TIME ZONE ?) AT TIME ZONE ? , interval '1' DAY)) d(date)
INNER JOIN event e ON ((e.end_date > d.date
AND e.end_date > ?)
OR e.end_date IS NULL)
AND e.date < d.date + interval '1' DAY
AND e.date < ?
AND d.date < ?
INNER JOIN subject ON subject.id = e.subject_id
INNER JOIN metric ON metric.id = e.metric_id
INNER JOIN event_configuration_version ON event_configuration_version.id = e.event_configuration_version_id
INNER JOIN event_configuration ON event_configuration.id = event_configuration_version.event_configuration_id
WHERE subject.project_id = ?
GROUP BY e.subject_id,
fromdate) AS sub1
GROUP BY sub1.fromdate,
sub1.maxeventlevel) AS sub2
ORDER BY sub2.fromdate,
sub2.eventlevel DESC
I don't think I can do anything in code after the query has already been performed, but I'm open to any code solutions that I've missed, though ideally we get the results back correctly from the SQL query itself. We do need to do most of the aggregation in the database itself but if there's something smart that that can be done elsewhere then that works too. The Java code generating and executing this query and transforming the result runs in a Spring Boot application and looks as follows:
public PeriodAggregationDTO[] getSubjectStatesReport(
AggregationPeriod aggregationPeriod, Integer aggregationPeriodAmount, UUID projectId,
List<UUID> eventTriggerIds, List<UUID> subjectIds, List<UUID> metricIds, List<EventLevel> eventLevels,
Date fromDate, Date toDate) {
// to avoid an even more complex native query, we obtain the project here so a) we are sure
// that this user has access
// and b) we can get the timezone already without additional joins later.
Project project = serviceUtil.findProjectByIdOrThrowApiException(projectId);
String timezoneId = project.getTimezoneId();
boolean skipEventTriggers = eventTriggerIds == null || eventTriggerIds.size() == 0;
boolean skipSubjects = subjectIds == null || subjectIds.size() == 0;
boolean skipMetrics = metricIds == null || metricIds.size() == 0;
boolean skipEventLevels = eventLevels == null || eventLevels.size() == 0;
StringBuilder whereClause = new StringBuilder();
whereClause.append(" WHERE subject.project_id = :projectId");
if (!skipEventTriggers) {
whereClause.append(" AND event_trigger.id in :eventTriggerIds");
}
if (!skipSubjects) {
whereClause.append(" AND subject_id in :subjectIds");
}
if (!skipMetrics) {
whereClause.append(" AND metric.id in :metricIds");
}
if (!skipEventLevels) {
whereClause.append(" AND e.event_level in :eventLevels");
}
String interval = String.format("'%d' %s", aggregationPeriodAmount, aggregationPeriod);
String series = "SELECT generate_series("
+ "date_trunc(:period, :fromDate AT TIME ZONE :timezoneId) AT TIME ZONE :timezoneId"
+ " , date_trunc(:period, :toDate AT TIME ZONE :timezoneId) AT TIME ZONE :timezoneId"
+ " , interval " + interval + ")";
String innersubquery = "SELECT e.subject_id" + ",MAX(e.event_level) as maxeventlevel"
+ ",d.date as fromdate"
+ " FROM (" + series + " ) d(date)"
+ " INNER JOIN event e ON ((e.end_date > d.date AND e.end_date > :fromDate)"
+ " OR e.end_date IS NULL) AND e.date < d.date + interval " + interval
+ " AND e.date < :toDate AND d.date < :toDate"
+ " INNER JOIN subject ON subject.id = e.subject_id"
+ " INNER JOIN metric ON metric.id = e.metric_id"
+ " INNER JOIN event_trigger_version ON event_trigger_version.id = e.event_trigger_version_id"
+ " INNER JOIN event_trigger ON event_trigger.id = event_trigger_version.event_trigger_id"
+ whereClause.toString()
+ " GROUP BY e.subject_id, fromdate";
String outersubquery = "SELECT" + " sub1.fromdate as fromdate"
+ ",sub1.maxeventlevel as eventlevel" + ",count(*) as count" + " FROM"
+ " (" + innersubquery + ") AS sub1"
+ " GROUP BY sub1.fromdate, sub1.maxeventlevel";
String queryString = "SELECT sub2.fromdate, sub2.eventlevel, sub2.count FROM ("
+ outersubquery + ") AS sub2"
+ " ORDER BY sub2.fromdate, sub2.eventlevel DESC";
Query query = em.createNativeQuery(queryString);
query.setParameter("projectId", projectId);
query.setParameter("timezoneId", timezoneId);
query.setParameter("period", aggregationPeriod.toString());
query.setParameter("fromDate", fromDate);
query.setParameter("toDate", toDate);
if (!skipEventTriggers) {
query.setParameter("eventTriggerIds", eventTriggerIds);
}
if (!skipSubjects) {
query.setParameter("subjectIds", subjectIds);
}
if (!skipMetrics) {
query.setParameter("metricIds", metricIds);
}
if (!skipEventLevels) {
List<Integer> eventLevelOrdinals =
eventLevels.stream().map(Enum::ordinal).collect(Collectors.toList());
query.setParameter("eventLevels", eventLevelOrdinals);
}
List<?> resultList = query.getResultList();
Stream<AggregateQueryEntity> stream = resultList.stream().map(obj -> {
Object[] array = (Object[]) obj;
Timestamp timestamp = (Timestamp) array[0];
Integer eventLevelOrdinal = (Integer) array[1];
EventLevel eventLevel = EventLevel.values()[eventLevelOrdinal];
BigInteger count = (BigInteger) array[2];
return new AggregateQueryEntity(timestamp, eventLevel, count.longValue());
});
return transformQueryResult(stream);
}
private PeriodAggregationDTO[] transformQueryResult(Stream<AggregateQueryEntity> stream) {
// we specifically use LinkedHashMap to maintain ordering. We also set Linkedlist explicitly
// because there are no guarantees for this list type with toList()
Map<Timestamp, List<AggregateQueryEntity>> aggregatesByDate = stream
.collect(Collectors.groupingBy(AggregateQueryEntity::getTimestamp,
LinkedHashMap::new, Collectors.toCollection(LinkedList::new)));
return aggregatesByDate.entrySet().stream().map(entryByDate -> {
PeriodAggregationDTO dto = new PeriodAggregationDTO();
dto.setFromDate((Date.from(entryByDate.getKey().toInstant())));
List<AggregateQueryEntity> value = entryByDate.getValue();
List<EventLevelAggregationDTO> eventLevelAggregationDTOS = getAggregatesByEventLevel(value);
dto.setEventLevels(eventLevelAggregationDTOS);
return dto;
}).toArray(PeriodAggregationDTO[]::new);
}
private List<EventLevelAggregationDTO> getAggregatesByEventLevel(
List<AggregateQueryEntity> value) {
Map<EventLevel, AggregateQueryEntity> aggregatesByEventLevel = value.stream()
.collect(Collectors.toMap(AggregateQueryEntity::getEventLevel, Function.identity(), (u, v) -> {
throw new InternalException(String.format("Unexpected duplicate event level %s", u));
}, LinkedHashMap::new));
return aggregatesByEventLevel.values().stream().map(aggregateQueryEntity -> {
EventLevelAggregationDTO eventLevelAggregationDTO = new EventLevelAggregationDTO();
eventLevelAggregationDTO.setEventLevel(aggregateQueryEntity.getEventLevel());
eventLevelAggregationDTO.setCount(aggregateQueryEntity.getCount());
return eventLevelAggregationDTO;
}).collect(Collectors.toCollection(LinkedList::new));
}
With another data class:
#Data
class AggregateQueryEntity {
private final Timestamp timestamp;
private final EventLevel eventLevel;
private final long count;
}
If you use timestamp with time zone, it should work just as you expect, because adding 1 day will sometimes add 23 or 25 hours:
SHOW timezone;
TimeZone
---------------
Europe/Vienna
(1 row)
SELECT * from generate_series(
TIMESTAMP WITH TIME ZONE '2019-03-28',
TIMESTAMP WITH TIME ZONE '2019-04-05',
INTERVAL '1' DAY
);
generate_series
------------------------
2019-03-28 00:00:00+01
2019-03-29 00:00:00+01
2019-03-30 00:00:00+01
2019-03-31 00:00:00+01
2019-04-01 00:00:00+02
2019-04-02 00:00:00+02
2019-04-03 00:00:00+02
2019-04-04 00:00:00+02
2019-04-05 00:00:00+02
(9 rows)
As you can see, this hinges on the current setting of timezone, which is respected by the date arithmetic performed by generate_series.
If you want to use this, you'll have to adjust the parameter for each query. Fortunately this is not difficult:
BEGIN; -- a transaction
SET LOCAL timezone = 'whatever'; -- for the transaction only
SELECT /* your query */;
COMMIT;
Simple enough solution will be patching it with java code rather than retrieving it from SQL directly - not saying it's impossible but maybe rather complicated. below is the java code that you can patch in.
Just like simple query get date, time and timezone from SQL result regardless of timezone difference.
date 1: 00:00
date 2: 00:00
date 3: 00:00
(now a DST change happens)
date 3: 23:00
date 4: 23:00
for example in your case Daylight savings takes place between date 3 and date 4. Consider date 3 as oldDate and date 4 as newDate variable in below java code.
Step 1 : Retrieve timezone from both the dates with newDate.getTimezoneOffset() and oldDate.getTimezoneOffset()
TimeZone timezone = TimeZone.getDefault();
{
// compare this 2 timezone to see if they are in different timezone that way you will see if Daylight saving changes took place. i.e. (GMT and BST (+1) )
// calculation will only be done if timezones are different
if(!(oldDate.getTimezoneOffset() == newDate.getTimezoneOffset()) ){
//save time to modify it later on
final long newTime = newDate.getTime();
//this function will check time difference caused by DST
long timediff = checkTimeZoneDiff(oldDate, newDate)
//update newDate (date 4) based on difference found.
newDate = new Date(time+timediff);
}
private long checkTimeZoneDiff(newDate,oldDate){
if(timezone.inDaylightTime(oldDate))
// this will add +1 hour
return timezone.getDSTSavings();
else if (timezone.inDaylightTime(newDate)){
/* this will remove -1 hour, in your case code should go through this bit resulting in 24 hour correct day*/
return -timezone.getDSTSavings()
else
return 0;
}
Hope that makes sense, you will be adding timediff to newDate(date 4). And continue same process for every other. See bubble short algorithm for checking values in that sequence.
How can i can reset the transactions number from ONE if new month is come.. for example, last entry is 17020005 become 17030001. The code is working but not reset transaction number from one when new month is come.
The code which i am using is
public void new(){
Date date =new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyMM");
String time = sdf.format(date);
try{
Connection con = new Connection ();
con.openConnection();
con.statement = con.dbConnection.createStatement();
ResultSet rs = con.statement.executeQuery("select right(id_sell,4) as id from sell");
if (rs.first()==false){
txtId.setText(time+"0001");
}
else
{
rs.last();
int no = rs.getInt(1)+1;
String cno = String.valueOf(no);
int pjg_cno = cno.length();
for (int i=0;i<4-pjg_cno;i++){
cno = "0"+cno;
}
txtId.setText(time+cno);
}
}catch (Exception e){
JOptionPane.showMessageDialog(null, "Fail!");
}
}
As Henry suggests, it looks like your "id_sell" values are made up of the year, month and a unique integer - if so, you could change your SQL query to include a WHERE clause to match the first four digits of your time string - WHERE id_sell LIKE '1703%'.
However, long term (and assuming you control the DB structure), I'd suggest thinking about storing those values separately - if you had a month field and a transaction_id field it would be much easier and more efficient to query this data.
I'd also suggest thinking about whether you could generate IDs on the database using a sequence - it's hard for this java code to guarantee uniqueness and raises potential concurrency issues.
I am trying to sum durations in the following format: "hh:mm:ss" (e.g.: "08:55:12") using Joda Time:
PeriodFormatter formatter = new PeriodFormatterBuilder()
.printZeroAlways().minimumPrintedDigits(2).appendHours()
.appendLiteral(":").printZeroAlways().printZeroAlways()
.minimumPrintedDigits(2).appendMinutes().appendLiteral(":")
.printZeroAlways().minimumPrintedDigits(2).appendSeconds()
.toFormatter();
Duration totalTime = Duration.ZERO;
for (Entry entry : entries) {
Period period = formatter.parsePeriod(entry.getTime());
Duration duration = period.toStandardDuration();
totalTime = totalTime.plus(duration);
}
Period totalPeriod = totalTime.toPeriod();
if (totalPeriod.getHours() < 10) {
hours = "0" + totalPeriod.getHours();
} else {
hours = Integer.toString(totalPeriod.getHours());
}
mTextView.setTextView(hours
+ String.format("%02d:%02d", totalPeriod.getMinutes(),
totalPeriod.getSeconds()));
For some reason, it is giving me wrong results (summed durations is way too long). Can you help me find the cause of this problem?
I think you have just forgotten a colon between hour-part and minute part causing the total sum looking like 2701:44 instead of 27:01:44 (this is an example for the sum of the three elements "03:20:45", "00:40:11", "23:00:48" which is correctly calculated by Joda-Time).
So your solution should finally look like:
String output =
hours + String.format(":%02d:%02d", totalPeriod.getMinutes(), totalPeriod.getSeconds());
System.out.println(output); // 27:01:44
But easier is just to reuse your formatter object for printing:
System.out.println(formatter.print(totalPeriod)); // 27:01:44
If you are interested in a pattern-based solution then check out my library Time4J with this example:
// input
String[] periods = { "03:20:45", "00:40:11", "23:00:48" };
// initialization
Duration.Formatter<ClockUnit> timeFormat =
Duration.Formatter.ofPattern(ClockUnit.class, "hh:mm:ss");
Duration<ClockUnit> dur = Duration.ofZero();
// calculate the sum
for (String entry : periods) {
dur = dur.plus(timeFormat.parse(entry));
}
dur = dur.with(Duration.STD_CLOCK_PERIOD); // normalization
System.out.println(timeFormat.format(dur)); // 27:01:44
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)
I have searched and found a lot of different things but none that actually help to get what I am looking for. I have two JComboBoxes in which the user can select different times. For example lets say 8:00, and 17:30. Now I want to be able to display the difference between those times, so in this case it would be 9.5. I want it to be in the 9.5, and not 9:30. But my code is doing 9.3, because it is just converting my string to a double.
Any help would be great
public void displaytotal() {
Object sunBobj, sunEobj, mon, tues, wed, thur, fri, sat;
double totalD;
sunBobj = jComboBox1.getSelectedItem();
sunEobj = jComboBox2.getSelectedItem();
String sunB = sunBobj.toString();
String sunE = sunEobj.toString();
try {
double sundB = Double.parseDouble(sunB.replace(":", "."));
double sundE = Double.parseDouble(sunE.replace(":", "."));
totalD = ((sundE - sundB)) * 24;
String totalS = "" + totalD;
jLabel17.setText(totalS);
} catch (NumberFormatException ex) {
JOptionPane.showMessageDialog(null, ex);
}
}
You could split the hh:mm string in hours / minutes:
String[] time = sunB.split(":");
int hours = Integer.parseInt(time[0]);
int minutes = Integer.parseInt(time[1]);
double decimalTime = hours + minutes / 60.0;