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 3 years ago.
Improve this question
How to get seconds of day (1 - 86400) in Go?
Just like http://joda-time.sourceforge.net/apidocs/org/joda/time/base/AbstractDateTime.html#getSecondOfDay()
Update/Clarifications
Wanted equivalent of the joda/SecondOfDay in golang
Expected to start at 0 and 86400 at end of the day
Required when rewriting in golang a java opensource function which in turn is using joda/secondOfDay
Googled '24 hour to seconds' to get 86400
While asking question I could only think of now.Unix()-yesterdayMidnight.Unix() and the simple accepted answer didn't come to my mind
Obviously didn't think about Daylight Saving
Wanted to see if there is some built in function or popular/standard library
If we define "seconds of day" as the "elapsed seconds since midnight", then to get correct result even on days when daylight saving time happens we should subtract the time representing midnight from the given time. For that, we may use Time.Sub().
func daySeconds(t time.Time) int {
year, month, day := t.Date()
t2 := time.Date(year, month, day, 0, 0, 0, 0, t.Location())
return int(t.Sub(t2).Seconds())
}
Testing it:
for _, t := range []time.Time{
time.Date(2019, 1, 1, 0, 0, 30, 0, time.UTC),
time.Date(2019, 1, 1, 0, 1, 30, 0, time.UTC),
time.Date(2019, 1, 1, 0, 12, 30, 0, time.UTC),
time.Date(2019, 1, 1, 12, 12, 30, 0, time.UTC),
} {
fmt.Println(daySeconds(t))
}
Output (try it on the Go Playground):
30
90
750
43950
Let's see how this function gives correct result when daylight saving time happens. In Hungary, 25 March 2018 is a day when the clock was turned forward 1 hour at 02:00:00, from 2 am to 3 am.
loc, err := time.LoadLocation("CET")
if err != nil {
fmt.Println(err)
return
}
t := time.Date(2018, 3, 25, 0, 0, 30, 0, loc)
fmt.Println(t)
fmt.Println(daySeconds(t))
t = t.Add(2 * time.Hour)
fmt.Println(t)
fmt.Println(daySeconds(t))
This outputs (try it on the Go Playground):
2018-03-25 00:00:30 +0100 CET
30
2018-03-25 03:00:30 +0200 CEST
7230
We print the daySeconds of a time being 30 seconds after midnight, which is 30 of course. Then we add 2 hours to the time (2 hours = 2*3600 seconds = 7200), and the daySeconds of this new time will be properly 7200 + 30 = 7230, even though the time changed 3 hours.
Note:
This function returns the nominal number of seconds of day in the (0 - 86399) range. If you're looking for the "number of seconds elapsed since midnight", which may not be in (0 - 86399) range due to daylight saving time, please see #icza's answer.
Update:
Please note also that the question refers to Joda Time implementation, which, according to Joda Time getSecondOfDay on DST switch day, seems to correspond to the nominal number of seconds implementation (as in my answer below) as opposed to the "number of seconds elapsed since midnight" (as in #icza's answer).
package main
import (
"fmt"
"time"
)
func getSecondOfDay(t time.Time) int {
return 60*60*t.Hour() + 60*t.Minute() + t.Second()
}
func main() {
t := time.Now()
fmt.Println(getSecondOfDay(t))
}
Related
I'm trying to normalize an array of elements in a time range. Say you have 20 bank transactions that occur on Jan 1st, 2022
transaction 1 - 2022/01/01
transaction 2 - 2022/01/01
...
transaction 20 - 2022/01/01
we don't have other data than the day they occurred, but we still want to assign them an hour of the day, so they end as:
transaction 1 - 2022/01/01 00:00
transaction 2 - 2022/01/01 ??:??
...
transaction 20 - 2022/01/01 23:59
In Go I have this function that try to calculate the normalization of a time of day for an index in an array of elements:
func normal(start, end time.Time, arraySize, index float64) time.Time {
delta := end.Sub(start)
minutes := delta.Minutes()
duration := minutes * ((index+1) / arraySize)
return start.Add(time.Duration(duration) * time.Minute)
}
Howeve, I get an unexpected calculation of 2022/1/1 05:59 for index 0 in an array of 4 elements in a time range of 2022/1/1 00:00 to 2022/1/1 23:59, instead I would expect to see 2022/1/1 00:00. The only that works fine these conditions is index 3.
so, what am I doing wrong with my normalization?
EDIT:
Here is the function fixed thanks to #icza
func timeIndex(min, max time.Time, entries, position float64) time.Time {
delta := max.Sub(min)
minutes := delta.Minutes()
if position < 0 {
position = 0
}
duration := (minutes * (position / (entries - 1)))
return min.Add(time.Duration(duration) * time.Minute)
}
There is an example: Let's say our start and end date is 2022/01/01 00:00 - 2022/01/01 00:03, also we have 3 entries in our array of bank transactions and that we want to get the normalized time for the transaction nÂș 3 (2 in the array):
result := timeIndex(time.Date(2022, time.January, 1, 0, 0, 0, 0, time.UTC), time.Date(2022, time.January, 1, 0, 3, 0, 0, time.UTC), 3, 2)
since there is only 4 minutes between the starting and ending times (from 00:00 to 00:03) and want to find the normalized time for the last entry (index 2) in the array (size 3) the result should be:
fmt.Printf("%t", result.Equal(time.Date(2022, time.January, 1, 0, 3, 0, 0, time.UTC))
// prints "true"
or the last minute in the range, which is 00:03.
Here is a reproducible example: https://go.dev/play/p/EzwkqaNV1at
Between n points there are n-1 segments. This means if you want to include start and end in the interpolation, the number of time periods (being delta) is arraySize - 1.
Also if you add 1 to the index, you can't possibly have start as the result (you'll skip the 00:00).
So the correct algorithm is this:
func normal(start, end time.Time, arraySize, index float64) time.Time {
minutes := end.Sub(start).Minutes()
duration := minutes * (index / (arraySize - 1))
return start.Add(time.Duration(duration) * time.Minute)
}
Try it on the Go Playground.
Also note that if you have many transactions (in the order of the number of minutes in a day which is around a thousand), you may easily end up having multiple transactions having the same timestamp (same hour and minute). If you want to avoid this, use a smaller precision than minute, e.g. seconds or milliseconds:
func normal(start, end time.Time, arraySize, index float64) time.Time {
sec := end.Sub(start).Seconds()
duration := sec * (index / (arraySize - 1))
return start.Add(time.Duration(duration) * time.Second)
}
Yes, this will result in timestamps where the seconds is also not necessarily zero, but will ensure different, unique timestamps for higher transaction numbers.
If you have transactions in the order of magnitude that is close to the number of seconds in a day (which is 86400), then you can complete drop this "unit" and use time.Duration itself (which is the number of nanoseconds). This will guarantee timestamp uniqueness even for the highest number of transactions:
func normal(start, end time.Time, arraySize, index float64) time.Time {
delta := float64(end.Sub(start))
duration := delta * (index / (arraySize - 1))
return start.Add(time.Duration(duration))
}
Testing this with 1 million transactions, here are the first 15 time parts (they defer only in their sub-second part):
0 - 00:00:00.00000
1 - 00:00:00.08634
2 - 00:00:00.17268
3 - 00:00:00.25902
4 - 00:00:00.34536
5 - 00:00:00.43170
6 - 00:00:00.51804
7 - 00:00:00.60438
8 - 00:00:00.69072
9 - 00:00:00.77706
10 - 00:00:00.86340
11 - 00:00:00.94974
12 - 00:00:01.03608
13 - 00:00:01.12242
14 - 00:00:01.20876
15 - 00:00:01.29510
16 - 00:00:01.38144
17 - 00:00:01.46778
18 - 00:00:01.55412
19 - 00:00:01.64046
Try this one on the Go Playground.
I have a fixed data structure given to me that has the fields YearDay and TimeOfDay. YearDay is the number of days that have passed in the current year, TimeOfDay is the number of seconds that have passed in the current day (up to 86400). YearDay is an int32, while TimeOfDay is a float64.
I want to convert this to time.Now().UnixNano() form but am unsure how to convert it. The time module has a YearDay(), but no inverse function given an yearDay (int32) (and probably a year), to give me the month and day in the month.
Ideally I'd like to somehow parse
d := time.Date(time.Year(), month, day, hour, min, sec, ms, time.UTC)
where month, day, hour, min, sec, ms was somehow predetermined, or something of equivalent that I can convert easily to any form I'd like (but mainly UnixNano()).
My best imagination would be a complicated switch statement that subtracted 31, 28(29), 30, 31 ... and to see when the int is finally negative to find the month and day, but it would have to be two switch statements with a leap year check to choose which switch block to use, while doing several remainder calculations on TimeOfDay. Is there a simpler and cleaner way?
Edit: I ended up making the following function while playing around with it, but I'll definitely be using Icza's solution. Nice to know days can overflow. Thanks!
func findMonthAndDay(yearDay int32) (int32, int32) {
year := time.Now().Year()
isLeapYear := year%400 == 0 || year%4 == 0 && year%100 != 0 // Calculates if current year is leapyear
// Determines which array to send to for loop
var monthsOfYear [12]int32
if isLeapYear {
monthsOfYear = [12]int32{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
} else {
monthsOfYear = [12]int32{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
}
var currentMonth int32
var currentDayInMonth int32
// Loop through array of months
for i := range monthsOfYear {
// If yearDay - next month #OfDays positive, not correct month
if yearDay-monthsOfYear[i] > 0 {
// Subtract month #OfDays and continue
yearDay = yearDay - monthsOfYear[i]
} else {
currentMonth = int32(i + 1) // Month found (+1 due to index at 0)
currentDayInMonth = yearDay // Remainder of YearDay is day in month
break
}
}
return currentMonth, currentDayInMonth
}
You may use Time.AddDate() to add the number of days to a time.Time value. It is OK to add days greater than 31, the implementation normalizes the result.
And convert TimeOfDay to time.Duration and use Time.Add() to add it. When converting to time.Duration, we may multiply it by 1e9 to get number of nanoseconds, so fractional seconds will be retained.
Example:
t := time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC)
fmt.Println(t)
var yearDay int32 = 100
var timeOfDay float64 = 70000.5
t = t.AddDate(0, 0, int(yearDay))
t = t.Add(time.Duration(timeOfDay * 1e9))
fmt.Println(t)
fmt.Println("Unix:", t.Unix())
fmt.Println("UnixNano:", t.UnixNano())
Output (try it on the Go Playground):
2020-01-01 00:00:00 +0000 UTC
2020-04-10 19:26:40.5 +0000 UTC
Unix: 1586546800
UnixNano: 1586546800500000000
Is there an option to set on pine script such that when a new order command is submitted, it would cancel the previous unfulfilled one?
if secondbuycond and firstbuycond and (time >= testPeriodStart and time <= testPeriodStop)
strategy.entry("buy", strategy.long, stop=((valuewhen(firstbuycond,open,0))*x))
strategy.exit("Trailing Stop", "buy", trail_points= trailPoints, trail_offset= trailOffset, when= testType == 'Trail Points')
//#version=3
strategy("My Strategy", overlay=true)
limit_price = 0
ts = timestamp(2018, 11, 13, 0, 0)
if (time > ts)
limit_price := 999
ts2 = timestamp(2018, 11, 22, 0, 0)
// here new price will be set to replace an order
if time > ts2
limit_price := 988
strategy.entry("BUY", strategy.long, limit=limit_price)
It's possible to replace just making an entry again with new price, but both entries must differ only in price (so the order ID and direction must be the same)
I tested the stragegy above in CHMF, dayly resolution.
I am new to GAS.
Need to write a script to execute the following calculation:
There are currently 87 employees who should be distributed for the week with a limit of 18 employees per day.
I have percentage allocation (col B). These percentages are based on other calculations and will change month over month.
What the team lead is currently doing - simple calculation in spreadsheet (multiplying % by 87). And then he manually adjusts numbers to have max of 18 per day (last column - is what needs to be at the end)
allocation number recount
Mon 0.21 18 18
Tue 0.08 7 7
Wed 0.22 19 18
Thu 0.12 10 11
Fri 0.25 22 18
Sat 0.07 6 10
Sun 0.05 4 4
Issues:
Total number of allocated staff after rounding is 86 (e.g. because 87*0.21 = 18.27 --> 18 employees)
If on some day it turns to be more than 18 employees (e.g. on Wed it is 22%*87=19 employees), only 18 people can be assigned to this day and remaining should be moved to the next "busiest" day (meaning day with the highest %). This is Friday, but on Friday we already have 22, so one from Wednesday should go to Thursday. And 4 extra from Friday go to Saturday.
Sounds complicated. But that's what I need - to automate adjustments, in other words to get column Recount from the column Number
I started the code, but have no idea how to proceed
Would be very grateful for any tips
function allocate() {
var ss=SpreadsheetApp.getActiveSpreadsheet();
var staff=ss.getSheetByName('staff');
var max = ss.getRange('B1').getValue();
for (var r=4; r<=10; r++)
{
var days=staff.getRange(r,2).getValue();
staff.getRange(r,3).setValue(days*max);
}
}
function round()
{
var ss=SpreadsheetApp.getActiveSpreadsheet();
var staff=ss.getSheetByName('staff');
for (var r=4; r<=10; r++)
{
var num=staff.getRange(r,3).getValue();
staff.getRange(r,3).setValue(Math.round(num));
}
}
You need to treat it on a week basis, not per day. Probably it is simplest to think of the task as removing marbles from a bag, until either your allocation quota is met, or the maximum draws are made. Then, advance to the next day.
E.g. (untested)
function allocate() {
const sheet = SpreadsheetApp.getActive().getSheetByName("weekly roster");
const numStaff = 50; // sheet.getRange("whatever cell you store this in").getValue();
const percentages = sheet.getRange("B4:B10").getValues();
const allotmentRange = sheet.getRange("C4:C10");
const maxPerDay = 5;
const allocated = [
[0],
[0],
[0],
[0],
[0],
[0],
[0]
];
var remaining = numStaff;
var day = 0;
while (remaining > 0 && day < allocated.length) {
if (allocated[day][0] < maxPerDay && allocated[day][0] / numStaff < percentages[day][0]) {
--remaining;
++allocated[day][0];
} else {
++day;
}
}
/* Add code to go back through allocated and add any remaining unused staff if the number is less than maxPerDay (i.e. ignoring percentage this time) */
// Write the worker allotment for the week.
allotmentRange.setValues(allocated);
}
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
Basic question:
for(int i=start;i<=end;i+=step){
System.out.println("Test");
}
start < end
How often is run through the loop, respectively what is the mathematical formula ?
We need to know what the values of start, end, and step are.
if:
start = 0;
end = 10;
step = 1;
It would loop 11 times, each time adding 1 to the previous value of i until it is <= 10. (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)
if:
start = 0;
end = 10;
step = 2;
It would loop 6 times, each time adding 2 to the previous value of i until it is <= 10. (0, 2, 4, 6, 8, 10)
if:
start = 10;
end = 100;
step = 10;
It would loop 10 times, each time adding 10 to the previous value of i until it is <= 100. (10, 20, 30, 40, 50, 60, 70, 80, 90, 100)
And so on.
Your for loop is shorthand for the following code:
int i = start;
if (i <= end) {
/* loop body */
i += step;
}
To answer your question, it will run ceiling((end - start + 1) / step) times. Walk through the logic on paper to see if you come to the same conclusion.