I'm using the Jquery TimeCircles plug in (https://github.com/wimbarelds/TimeCircles) as a timer on my application, but I would like to have it so that there is only one circle with the minutes and seconds in the middle, like 15:40. I would like the seconds to keep ticking down, but the circle should animate according to the minutes only. Currently I have two circles showing the minutes and seconds.
I would like to start the timer at 50 minutes, and then countdown to 0 minutes and 0 seconds. Is there any way I can have the time display in the format MM:SS inside the one circle, and have the number of seconds ticking down, and the circle animating to the number of minutes ticking down only?
Thank you so much!
I actually had a fairly similar request the other day on github:
https://github.com/wimbarelds/TimeCircles/issues/68
You could change it to something like:
var $container = $('#DateCountdown .textDiv_Minutes');
$container.find('h4').text('Time left');
var $original = $container.find('span');
var $clone = $original.clone().appendTo($container);
$original.hide();
$('#DateCountdown').TimeCircles().addListener(function(unit, value, total) {
total = Math.abs(total);
var minutes = Math.floor(total / 60) % 60;
var seconds = total % 60;
if(seconds < 10) seconds = "0" + seconds;
$clone.text(minutes + ':' + seconds);
}, "all");
You'd need to use the TimeCircles options that make it only display the Minutes circle.
Related
I have some code that simulates a timer that will look at the start time, store that into localStorage and compare that to Date.now() and will correctly simulate a working timer by updating a state variable that increments on a setInterval every 1 second. It works well even after page reload.
Naturally the timer counts up in milliseconds, so i wrote a function that formats the time into hours:minutes:seconds. The issue now is that the counter, which was updating in real time when unformatted, now that it goes into a function to format, what is returned is correctly formatted but does not increment in real time, i suspect something to do with function not being called again even though the state is being incremented every second.
My question would be is there a way to call the function every time the state changes like a useEffect? Maybe a custom hook?
Here's my code:
const date = new Date()
const [time, setTime] = useState(date.getTime())
//starts timer on button click
function startTimer() {
setStart(true)
localStorage.setItem('startTime', date.getTime())
}
//converts ms time into hours:minutes:seconds
function msToTime(duration) {
let seconds = Math.floor((duration / 1000) % 60),
minutes = Math.floor((duration / (1000 * 60)) % 60),
hours = Math.floor((duration / (1000 * 60 * 60)) % 24)
hours = (hours < 10) ? "0" + hours : hours
minutes = (minutes < 10) ? "0" + minutes : minutes
seconds = (seconds < 10) ? "0" + seconds : seconds
return hours + ":" + minutes + ":" + seconds
}
//the interval that updates time state every second
useEffect(() => {
const timer = setInterval(() => {
setTime(prev => prev+1)
},1000)
return () => {
clearInterval(timer)
}
},[time])
//return the difference between start and time state and formats it
return <h3>{msToTime(Math.abs(+localStorage.getItem('startTime') - time))}</h3>
Everything is fine in your code except that you have overseen one compatibility issue. In your setTime function, the prev argument is in milliseconds, but you're adding only one millisecond to it every second. Change it to the following:
setTime(prev => prev + 1000)
You can also use:
setTime(date.getTime())
I'm trying to map the max number of consecutive days with rain <1 mm in Google Earth Engine.
This is the link to the code
https://code.earthengine.google.com/22b5c20d2700a2ffb5989f892838ac58
First I reclassify the collection with 0 if rain <=1 and 1 if >1.
Then I run the code that should count the days of the longest dry period, but it is able to do so only if the dry period reach the end of the time period.
For instance if I am looking for the longest dry period in 4 days timestep i get the following series:
rain days 1 2 3 4 output
0,0,1,1 = 0 dry days
0,1,0,0 = 2 dry days
0 = rain<=1 and
1 = rain>1 (as per the first step)
Does anyone can help in solving this?
Thanks
I don't think you were far off in your code that you provided. To keep track of the dry spells you have to use .iterate(). I took a stab at your application in a little different way where instead of classifying the data before the iteration, I calculate which pixels are dry each day and carry over the accumulated days that a pixel is dry, otherwise it is set to zero:
// DATA
var collection = ee.ImageCollection("UCSB-CHG/CHIRPS/DAILY");
// Define time range
var startyear = 2000;
var endyear = 2017;
var startmonth = 1;
var endmonth = 12;
// Set date in ee date format
var startdate = ee.Date.fromYMD(startyear,startmonth,1);
var enddate = ee.Date.fromYMD(endyear,endmonth,31);
// Filter data
var datain_t = collection.filterDate(startdate, enddate)
.filter(ee.Filter.calendarRange(startmonth,endmonth, 'month'))
.select("precipitation").map(function(img){
return img.addBands(ee.Image.constant(0).uint8().rename('counter'));
})
.sort('system:time_start');
// // START
var dataset = datain_t
.filterDate("2016-08-01","2016-08-30")
.sort('system:time_start:');
print(dataset,"dataset");
var precipThresh = 1; // mm
function drySpells(img, list){
// get previous image
var prev = ee.Image(ee.List(list).get(-1));
// find areas gt precipitation threshold (gt==0, lt==1)
var dry = img.select('precipitation').lt(precipThresh);
// add previous day counter to today's counter
var accum = prev.select('counter').add(dry).rename('counter');
// create a result image for iteration
// precip < thresh will equal the accumulation of counters
// otherwise it will equal zero
var out = img.select('precipitation').addBands(
img.select('counter').where(dry.eq(1),accum)
).uint8();
return ee.List(list).add(out);
}
// create first image for iteration
var first = ee.List([ee.Image(dataset.first())]);
// apply dry speall iteration function
var maxDrySpell = ee.ImageCollection.fromImages(
dataset.iterate(drySpells,first)
).max(); // get the max value
// display results
Map.addLayer(maxDrySpell.select('counter'),{min:0,max:30,palette:'#9ecae1,#ffffff,#ffeda0,#feb24c,#f03b20'},'Max Dry Spells');
Here is the link to the code: https://code.earthengine.google.com/80b4c0f7e82a5f0da316af1d2a55dd59
Don't try to run this analysis for too long of a time period or Earth Engine will give an error. I hope this helps!
I'd like to start by stating I have very little experience with Angular as this is the first project I've worked on that uses it.
Within the controller I make an AJAX call which returns a json. One of the json objects is minutes in the following format: 1385
I'd like to convert this number into something like this: 8d 15h 0m using an Angular filter
Im wondering how this would be possible?
Answer
Yes. It is 100% possible. Create a filter like below and add your specific date calculation
inside the filter.
How to do the date calculation:
In terms of the actual date calculation, it will be nothing more than regular JavaScript logic. Here you have a few options:
The native Date() object will expose various .getSomething()
functions
MomentJS is also good, as its a library designed for these things specifically
Manual calculation
If you'd like to know how to do this manually. Conceptually the calculation is something like below... the idea is, a rolling calculation where you get the higher time unit, then keep subtracting it from the next calculation, carrying the leftover time along.
Input = Original Minute value
Days = Input / 60 [mins in an hour] / 24 [total hours in day]
Hours = Leftover / 60 [mins in an hour]
Mins = Leftover
A quick search on SO yielded this solution for a custom calculation of sorts. I used the linked calculation on my sample below.
Example
var app = angular.module('app', []);
app.controller('MainCtrl', function($scope) {})
.filter('myDateFilter', ['$filter',
function($filter) {
return function(input) {
// set minutes to seconds
var seconds = input * 60
// calculate (and subtract) whole days
var days = Math.floor(seconds / 86400);
seconds -= days * 86400;
// calculate (and subtract) whole hours
var hours = Math.floor(seconds / 3600) % 24;
seconds -= hours * 3600;
// calculate (and subtract) whole minutes
var minutes = Math.floor(seconds / 60) % 60;
return days + 'd ' + hours + 'h ' + minutes + 'm ';
}
}
]);
<!DOCTYPE html>
<html ng-app="app">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.25/angular.min.js"></script>
</head>
<body ng-controller="MainCtrl">
1385 minutes = {{ 1385 | myDateFilter }}
</body>
</html>
I suggest a slightly shorter version as an alternative, that uses new Date() object and gets its components individually with predefined methods. It works the same way and uses less computations.
Here is a demo:
var app = angular.module('app', []);
app.controller('MainCtrl', function($scope) {});
app.filter('myDateFilter', ['$filter',
function($filter) {
return function(input) {
var inp = new Date(0, 0, 0, 0, input, 0); // assumes minutes as an input
var m = inp.getMinutes();
var h = inp.getHours();
var d = inp.getDay();
return d + 'd ' + h + 'h ' + m + 'm ';
}
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.25/angular.min.js"></script>
<div ng-app="app" ng-controller="MainCtrl">
1385 minutes = {{ 1385 | myDateFilter }}
</div>
Here is a pipe you can copy/paste for angular 6+. I made it a bit more robust too:
import { Pipe, PipeTransform } from '#angular/core';
/**
* Format a value in minutes as [x(d| days)] y(h| hours) z(m| minutes)
*
* Usage:
* value | hoursMinutes // 0d 3h 20m
* value | hoursMinutes: 'long':false // 3 hours 20 minutes
*/
#Pipe({
name: 'hoursMinutes'
})
export class HoursMinutesPipe implements PipeTransform {
transform(minutes: number, format = 'short', includeDays = true): any {
let formatted = '';
// set minutes to seconds
let seconds = minutes * 60;
// calculate (and subtract) whole days
let days = 0;
if (includeDays) {
days = Math.floor(seconds / 86400);
seconds -= days * 86400;
formatted = `${days}d `;
}
// calculate (and subtract) whole hours
const hours = Math.floor(seconds / 3600) % 24;
seconds -= hours * 3600;
// calculate (and subtract) whole minutes
const min = Math.floor(seconds / 60) % 60;
formatted += `${hours}h ${min}m`;
if ('long' === format) {
formatted = formatted.replace('d', ' days');
formatted = formatted.replace('h', ' hours');
formatted = formatted.replace('m', ' minutes');
}
return formatted;
}
}
I am implementing a function to have a countdown in Angular form current time - existing time in future. If the time has elapsed then display a message. Timer ran out in ..... HH:MM:SS
The end time. Lets call it endTime eg:
9/15/2016 9:16:00 PM
Current time. Time current moment we live.
Lets call it currentTime.
The goal is to get a timer that is Current time - end time. Save it to a Variable TotalHours.
Then calculate the time remaining for NOW to total hours. For example TotalHours = 5. And NOW is 9/14/2016 1:16:00 PM then FinalCountDown = 6:16:00 PM. That is the timer I want running...
Here is how I am doing it...
if (info.endTime) {
var CurrentTime = new Date().toLocaleString('en-US');
moment.locale(); // en
var TotalHours = moment.utc(moment(info.diffTime, "DD/MM/YYYY HH:mm:ss").diff(moment(CurrentTime, "DD/MM/YYYY HH:mm:ss"))).format("HH:mm:ss");
info.finalCountDown= TotalHours;
};
The issue here is the following:
Case 1:
endTime = 9/15/2016 9:16:00 AM
currentTime = 9/15/2016 1:21:00 PM
TotalHours = 4:05:00
But... if its after next 2 days...
Case 2:
endTime = 9/17/2016 9:16:00 AM
currentTime = 9/15/2016 1:21:00 PM
TotalHours = 4:05:00
Total hours is still the same...
I need it to add 24hours + 24 hours + extra time = 48 + 4:05:00 = 52:05:00
also I want it to display as: 52h:05m:00s
Please let me know how to solve this...
A quick and dirty solution would be to simply convert the difference between the two date/time objects to milliseconds and then do some math on the milliseconds and format the output as follows:
var currentTime = new Date("9-15-2016 13:21:00");
var endTime = new Date("9-17-2016 09:16:00");
var ms = (endTime - currentTime); // ms of difference
var days = Math.round(ms/ 86400000);
var hrs = Math.round((ms% 86400000) / 3600000);
var mins = Math.round(((ms% 86400000) % 3600000) / 60000);
$scope.finalCountdown = (days + "d:" + hrs + " h:" + mins + "m left");
You could add in a calculation for the seconds if you needed and you can do some formatting of the numbers to have leading zeros.
However, doing this doesn't account for issues such as leap-years and other data and time anomalies. A better suggestion would be to use angular-moment which utilizes Moment.js as it can handle differences and formatting with ease.
I want to display time duration of a video in silverlight 3.0 application. The format should be like 00:20 / 05:00 . ( Current Video time / Total Video Time). How to get it??.
TimeSpan _duration = mediaElement.NaturalDuration.TimeSpan;
var totalTime = string.Format("{0:00}:{1:00}", (_duration.Hours * 60) + _duration.Minutes, _duration.Seconds);
TimeSpan remaining = _duration.Subtract(mediaElement.Position);
var currentTime = string.Format("{0:00}:{1:00}", (remaining.Hours * 60) + remaining.Minutes, remaining.Seconds);
string result = string.formar("{0}/{1}",totalTime,currentTime);
Try this, Hope this can help.
Regards.