java code to use timestamp items inside a loop - java

ResultSet rs2 = stmt2.executeQuery("SELECT starttime FROM user_req ORDER BY req_id ASC LIMIT 1");
Timestamp a;
while (rs2.next()) {
a = rs2.getTimestamp("starttime");
System.out.println(a);
long t=a.getTime();
long m=5*60*1000;
Timestamp b= new Timestamp(t+m);
System.out.println(b);
}
This code produces two timestamps: 2013-12-12 09:00:00 and 2013-12-12 09:05:00.
In this code I get two timestamp items one with adding 5 min to the previous one, can anyone pls help me out in how to put it in a for loop such that it should start wd the "timestamp a" till "timestamp b" and it should increment with 1 minute, so that I can perform roundrobin code in it. please help me how to iterate over the timestamps.

Simply:
for(long current = a ; current <= a+5*60*1000 ; current += 60*1000) {
// do something with current
}

You can use :
long starTime=a.getTime();
long endTime=starTime+5*60*1000;
for (long currTime = starTime; currTime < endTime; currTime += 60*1000) {
// Do your stuff, currTime will increment in 1 minute steps
}

Related

Android: get UsageStats per hour

I use UsageStats feature of Android, but the smallest interval is DAILY INTERVAL.
long time = System.currentTimeMillis();
List<UsageStats> appList = manager.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, time - DAY_IN_MILLI_SECONDS, time);
How can I get UsageStats in an hourly interval?
All credit goes to this answer. I have learned from that one.
How can we collect app usage data for customized time range (e.g. for per 1 hour)?
We have to call queryEvents(long begin_time, long end_time) method as it will provide us all data starting from begin_time to end_time. It give us each app data through foreground and background events instead of total spent time like queryUsageStats() method. So, using foreground and background events time stamp, we can count the number of times an app has been launched and also can find out the usage duration for each app.
Implementation to Collect Last 1 Hour App Usage Data
At first, add the following line in the AndroidManifest.xml file and also request user to get permission of usage access.
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
Add the following lines inside any method
long hour_in_mil = 1000*60*60; // In Milliseconds
long end_time = System.currentTimeMillis();
long start_time = end_time - hour_in_mil;
Then, call the method getUsageStatistics()
getUsageStatistics(start_time, end_time);
getUsageStatistics methiod
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
void getUsageStatistics(long start_time, long end_time) {
UsageEvents.Event currentEvent;
// List<UsageEvents.Event> allEvents = new ArrayList<>();
HashMap<String, AppUsageInfo> map = new HashMap<>();
HashMap<String, List<UsageEvents.Event>> sameEvents = new HashMap<>();
UsageStatsManager mUsageStatsManager = (UsageStatsManager)
context.getSystemService(Context.USAGE_STATS_SERVICE);
if (mUsageStatsManager != null) {
// Get all apps data from starting time to end time
UsageEvents usageEvents = mUsageStatsManager.queryEvents(start_time, end_time);
// Put these data into the map
while (usageEvents.hasNextEvent()) {
currentEvent = new UsageEvents.Event();
usageEvents.getNextEvent(currentEvent);
if (currentEvent.getEventType() == UsageEvents.Event.ACTIVITY_RESUMED ||
currentEvent.getEventType() == UsageEvents.Event.ACTIVITY_PAUSED) {
// allEvents.add(currentEvent);
String key = currentEvent.getPackageName();
if (map.get(key) == null) {
map.put(key, new AppUsageInfo(key));
sameEvents.put(key,new ArrayList<UsageEvents.Event>());
}
sameEvents.get(key).add(currentEvent);
}
}
// Traverse through each app data which is grouped together and count launch, calculate duration
for (Map.Entry<String,List<UsageEvents.Event>> entry : sameEvents.entrySet()) {
int totalEvents = entry.getValue().size();
if (totalEvents > 1) {
for (int i = 0; i < totalEvents - 1; i++) {
UsageEvents.Event E0 = entry.getValue().get(i);
UsageEvents.Event E1 = entry.getValue().get(i + 1);
if (E1.getEventType() == 1 || E0.getEventType() == 1) {
map.get(E1.getPackageName()).launchCount++;
}
if (E0.getEventType() == 1 && E1.getEventType() == 2) {
long diff = E1.getTimeStamp() - E0.getTimeStamp();
map.get(E0.getPackageName()).timeInForeground += diff;
}
}
}
// If First eventtype is ACTIVITY_PAUSED then added the difference of start_time and Event occuring time because the application is already running.
if (entry.getValue().get(0).getEventType() == 2) {
long diff = entry.getValue().get(0).getTimeStamp() - start_time;
map.get(entry.getValue().get(0).getPackageName()).timeInForeground += diff;
}
// If Last eventtype is ACTIVITY_RESUMED then added the difference of end_time and Event occuring time because the application is still running .
if (entry.getValue().get(totalEvents - 1).getEventType() == 1) {
long diff = end_time - entry.getValue().get(totalEvents - 1).getTimeStamp();
map.get(entry.getValue().get(totalEvents - 1).getPackageName()).timeInForeground += diff;
}
}
smallInfoList = new ArrayList<>(map.values());
// Concatenating data to show in a text view. You may do according to your requirement
for (AppUsageInfo appUsageInfo : smallInfoList)
{
// Do according to your requirement
strMsg = strMsg.concat(appUsageInfo.packageName + " : " + appUsageInfo.launchCount + "\n\n");
}
TextView tvMsg = findViewById(R.id.MA_TvMsg);
tvMsg.setText(strMsg);
} else {
Toast.makeText(context, "Sorry...", Toast.LENGTH_SHORT).show();
}
}
AppUsageInfo.class
import android.graphics.drawable.Drawable;
class AppUsageInfo {
Drawable appIcon; // You may add get this usage data also, if you wish.
String appName, packageName;
long timeInForeground;
int launchCount;
AppUsageInfo(String pName) {
this.packageName=pName;
}
}
How can I customize these codes to collect per 1 hour data?
As you want to get per hour data, please change the end_time and start_time value for every hour data. For instance: If I would try to collect past per hour data (for past 2 hour data). I would do the following thing.
long end_time = System.currentTimeMillis();
long start_time = end_time - (1000*60*60);
getUsageStatistics(start_time, end_time);
end_time = start_time;
start_time = start_time - hour_in_mil;
getUsageStatistics(start_time, end_time);
However, you may use a Handler to skip repeatedly writing start_time and end_time to change value of these variables. Each time data will be collected for one hour, a task will be completed and after automatically changing the values of the variables, you will again call the getUsageStatistics method.
Note: Maybe, you will not be able to retrieve data for more than past 7.5 days as events are only kept by the system for a few days.
Calendar cal = (Calendar) Calendar.getInstance().clone();
//I used this and it worked, only for 7 days and a half ago
if (daysAgo == 0) {
//Today - I only count from 00h00m00s today to present
end = cal.getTimeInMillis();
start = LocalDate.now().toDateTimeAtStartOfDay().toInstant().getMillis();
} else {
long todayStartOfDayTimeStamp = LocalDate.now().toDateTimeAtStartOfDay().toInstant().getMillis();
if (mDaysAgo == -6) {
//6 days ago, only get events in time -7 days to -7.5 days
cal.setTimeInMillis(System.currentTimeMillis());
cal.add(Calendar.DATE, daysAgo + 1);
end = cal .getTimeInMillis();
start = end - 43200000;
} else {
//get events from 00h00m00s to 23h59m59s
//Current calendar point to 0h0m today
cal.setTimeInMillis(todayStartOfDayTimeStamp);
cal.add(Calendar.DATE, daysAgo + 1);
end = calendar.getTimeInMillis();
cal.add(Calendar.DATE, -1);
start = calendar.getTimeInMillis();
}
}
I don't think it's possible, even if you ask for data in the middle of an interval, it looks like the data is stored in buckets and the minimum bucket is a day.
In UsageStatsManager documentation, it says:
A request for data in the middle of a time interval will include that interval.
Also, INTERVAL_BEST is not a real interval, it just selects one of the available intervals for the given time range. In
UsageStatsManager.java source code, it says:
/**
* The number of available intervals. Does not include {#link #INTERVAL_BEST}, since it
* is a pseudo interval (it actually selects a real interval).
* {#hide}
*/
public static final int INTERVAL_COUNT = 4;
Yes, Android is providing minimum INTERVAL_DAILY. But for the best result, you can use INTERVAL_BEST. Android is giving the best interval timer for the given time range in queryUsageStats(int, long, long).
Happy coding...

Postgresql: create a query that uses generate_series with an interval that correctly takes DST changes into account and flattens on true calendar days

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.

Summing durations using Joda Time

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

java code to store milliseconds into an array [closed]

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 ;-)

How to find the difference of two timestamps in java?

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.

Categories

Resources