I have a telegram bot that helps users to notify if they late for work. So they write as I will come at 12:00 and I get string I have to check if the time they wrote is permitted.
For Example: If they write to me I will come at 12:00 but time.Now() is 11:00 so I give them error
The problem is how to compare their local time with time which they sent via bot if they located around the world and my bot server tunning in another country
How to get their local time?
I have 2 solution
Get user location via IP, GPS
use if, case statement
Do u have any other idea? I will grateful if u help me.
Code snippet to compare with my local time
func getArrivalTime(text string, status string) (time.Time, error) {
var arrivalTime time.Time
rule := regexp.MustCompile(`([0-9]|1[0-9]|2[0-3])((\:)|(\.))[0-5][0-9]`)
timeStr := rule.FindStringSubmatch(text)
if len(timeStr) == 0 {
log.Println("ERROR OCCURED")
return time.Time{}, errors.New("Wrong time format or omitted")
}
timeFormatted := strings.Replace(timeStr[0], ".", ":", 1)
date := fmt.Sprintf("%vT%v:00+00:00", time.Now().Format("2006-01-02"), timeFormatted)
arrivalTime, err := time.Parse(time.RFC3339, date)
if strings.Contains(text, "/завтра") && status == "late" {
arrivalTime = arrivalTime.Add(time.Hour * 24)
}
arrivalTimeUtc, _ := ConvertToUTC(arrivalTime)
nowUtc, _ := ConvertToUTC(time.Now())
nowUtc = nowUtc.Add(time.Hour * 5)
if arrivalTimeUtc.After(nowUtc) == false && status != "lateButInOffice" {
log.Println("ERROR OCCURED")
return time.Time{}, errors.New("Wrong time format or omitted")
}
if err != nil {
log.Println(err)
}
return arrivalTime, err
}
Related
I am proto-typing an application using Google new People API. During my testing I have added and deleted contacts in batches, to see how many can be added per minute and per day in total.
I understand the documentation say how many can be added per minute, but from my testing I don't seem to get anywhere close to this. Even when reviewing my metrics, my request is far long than the supposed limits per minute and per day.
My main question I have is after a couple of attempts across a service account on 3 of my gmail account's I am now getting back googleapi: Error 429: MY_CONTACTS_OVERFLOW_COUNT, rateLimitExceeded. I can't find any mention of MY_CONTACTS_OVERFLOW_COUNT online. I assumed from the error it meant I have too many contacts, but when running a delete script it appears I don't have any at all.
This response is returned for all 3 accounts on my development machine now for longer than 24 hours, which is making me believe I have possibly been blocked and not rate limited?
Client code for running the test:
package main
import (
"context"
"log"
"google.golang.org/api/people/v1"
"os"
"bufio"
"time"
//"github.com/davecgh/go-spew/spew"
)
func chunks(xs []string, chunkSize int) [][]string {
if len(xs) == 0 {
return nil
}
divided := make([][]string, (len(xs)+chunkSize-1)/chunkSize)
prev := 0
i := 0
till := len(xs) - chunkSize
for prev < till {
next := prev + chunkSize
divided[i] = xs[prev:next]
prev = next
i++
}
divided[i] = xs[prev:]
return divided
}
func main(){
ctx := context.Background()
srv, err := people.NewService(ctx)
if err != nil {
log.Fatalf("Unable to create people Client %v", err)
}
file, err := os.Open("test125k.txt")
if err != nil {
log.Fatalf("failed opening file: %s", err)
}
scanner := bufio.NewScanner(file)
scanner.Split(bufio.ScanLines)
var txtlines []string
for scanner.Scan() {
txtlines = append(txtlines, scanner.Text())
}
chunkEmails := chunks(txtlines,200)
count := 0
var validPeopleResources []string
log.Printf("Started")
for i,chunk := range chunkEmails{ //
var contacts people.BatchCreateContactsRequest
contacts.ReadMask = "emailAddresses,photos"
for _,chunkEmail := range chunk{
var contact people.ContactToCreate
var person people.Person
var personEmails people.EmailAddress
personEmails.Value = chunkEmail
var AllEmails = [](*people.EmailAddress){
&personEmails,
}
person.EmailAddresses = AllEmails
contact.ContactPerson = &person
contacts.Contacts = append(contacts.Contacts, &contact)
}
r,err := srv.People.BatchCreateContacts(&contacts).Do()
if err != nil {
log.Printf("Unable to create contacts")
log.Printf(err.Error())
log.Fatalf("")
}
var contactEmail string
var resource string
for _, validPeople := range r.CreatedPeople {
contactEmail = validPeople.Person.EmailAddresses[0].Value
resource = validPeople.Person.ResourceName
validPeopleResources = append(validPeopleResources,resource)
}
count = count + 1
if count == 2 {
var contactToDelete people.BatchDeleteContactsRequest
contactToDelete.ResourceNames = validPeopleResources
_,err = srv.People.BatchDeleteContacts(&contactToDelete).Do()
if err != nil {
log.Printf("Unable to delete contacts")
log.Printf(err.Error())
log.Fatalf("")
}
validPeopleResources = nil
count = 0
log.Printf("performed delete")
}
log.Printf("%d comlpeted",i)
time.Sleep(10 * time.Second)
}
}
"MY_CONTACTS_OVERFLOW_COUNT" happens when you try to insert new contacts to the Google account, but they already have the maximum number of contacts.
The max limit is 25,000, since 2011: https://workspaceupdates.googleblog.com/2011/05/need-more-contacts-in-gmail-contacts.html
It should be noted here that Google also takes the deleted contacts into account for calculating the count. You can find the deleted contacts in the Contacts Trash. These contacts will be cleared after 30 days.
I am trying to find a way to check if the current time is inside a time window.
The inputs are:
upgradeDay []string - a slice of days (for instance ["Sunday", "Tuesday"])
upgradetime string - hour:minute (for instance "22:04")
upgradeDuration int64 - amount of time, from the upgradetime at which the time window is valid. it can be up to 12 hours.
Full example:
upgradeDay = ["Sunday", Tuesday"] , upgradetime = "10:00", upgradeDuration = 2 -> the time windows is at every Sunday and Tuesday, from 10:00 to 12:00 o'clock.
I tried to write the following function, but it's not working in transition between days/months/years:
func isInsideTimeWindow(upgradeDay []string, upgradeTime string, upgradeDuration int64) bool {
now := time.Now()
ut := strings.Split(upgradeTime, ":")
hour, _ := strconv.Atoi(ut[0])
min, _ := strconv.Atoi(ut[1])
// !! not working when now it's Monday 00:01 and got: upgradeDay = ["Sunday"], upgradeTime = 23:59, upgradeDuration = 2
twStart := time.Date(now.Year(), now.Month(), now.Day(), hour, min, 0, 0, now.Location())
twEnd := twStart.Add(time.Hour * time.Duration(upgradeDuration))
if !(now.After(twStart) && now.Before(twEnd)) {
return false
}
wd := now.Weekday().String()
for i := range upgradeDay {
if upgradeDay[i] == wd {
return true
}
}
return false
}
Does someone got an idea on how to solve that in Go?
Here is one approach to the problem:
package main
import "time"
type window struct { time.Time }
func (w window) isDay(s string) bool {
return w.Weekday().String() == s
}
func (w window) isHourRange(begin, end int) bool {
return w.Hour() >= begin && w.Hour() <= end
}
func main() {
w := window{
time.Now(),
}
{
b := w.isDay("Friday")
println(b)
}
{
b := w.isHourRange(20, 23)
println(b)
}
}
This assume only one day is valid, so you would need to modify this to handle
multiple days. This should get you started though.
There is a lot of complexity in times. For instance:
What if an upgrade day is "Søndag" (Danish) instead of "Sunday"?
Should we work in local time, or UTC? If local, whose location counts? If the server is in London and I am in San Francisco, do we use the server's time, or my time?
If the upgrade interval includes 2 AM, does that count 2 AM PDT and then 2 AM PST as well? These times are one hour apart where I live. If the interval starts at 2 AM and ends at 2:59:59, that time does not exist on one day of the year in many areas with one hour DST shift.
If you get to ignore all these complexities—internationalization (i18n), localization (l10n), DST, and so on—there's still a bit of a problem with the fact that someone can set the date and time, or the upgrade itself might take some time, but usually we get to ignore these too.
Note that Go's time.Now() returns local time—but, whose location? As we have not yet answered the whose time zone to use question yet, we might want to avoid worrying about this. Given the rest of your input constraints, let's write a function to determine if a supplied time meets the input constraints, rather than if time.Now() does so. The caller can then provide either a UTC time or a wall-clock time in the user's location:
someNow = time.Time()
localNow = someNow.In(location) // from time.LoadLocation() or similar
We also have something that seems at odds with your types:
upgradeDuration int64 - amount of time, from the upgradetime at which the time window is valid. it can be up to 12 hours
A value in hours that is between 0 and 12 inclusive fits easily in plain int. Is this already a time.Duration value expressed in nanoseconds? If so, why is it int64 and not time.Duration? Or is it a value in seconds, and therefore can be between 0 and 43200? If so, it still fits in int.
I made a bunch of assumptions and came up with the following, which you can try out on the Go Playground.
package main
import (
"fmt"
"strconv"
"strings"
"time"
)
// startOK determines whether the given starting-time is within a
// time window.
//
// The window starts at a time given as two integers,
// h and m, representing hours and minutes, and extends for
// the given duration d in hours, which in general should not
// extend into another day. If it does extend past the end of
// the day into the next day, we ignore the extension.
//
// The days on which the time *is* in that window are further
// limited by the days[] slice of Weekday values.
//
// Note: it would probably be sensible to return a time.Duration
// value that is how long it will be until the next OK time, but
// we leave that as an exercise.
//
// It would also be sensible to allow the duration d to extend
// into the next day, which is also left as an exercise.
func startOK(when time.Time, days []time.Weekday, h, m, d int) bool {
// Find OK-to-start time, and end-time. If end exceeds
// 24*60, we ignore the extra end time, rather than
// allowing some minutes into the next day.
start := h*60 + m
end := start + d*60
// Convert when to hour-and-minute and see if we are
// in the allowed range.
wh, wm, _ := when.Clock()
now := wh*60 + wm
if now < start || now >= end {
// Not in hh:mm through hh+d:mm; say no.
return false
}
// The time-of-day is OK; check the day-of-week.
// We could do this earlier but by positioning it
// here, we leave room to check to see if it's
// the *next* day, if needed.
if !func(wd time.Weekday) bool {
for _, allowed := range days {
if wd == allowed {
return true
}
}
return false
}(when.Weekday()) {
return false // when.Weekday() not in days[]
}
// time is OK, day is OK
return true
}
// startOKstr is like startOK but the window starts at a time
// given as a string encoded as hh:mm, with the days being a
// slice of strings instead of Weekday. Because of these strings,
// parsing can produce an error, so this function has an error
// return.
func startOKStr(when time.Time, days []string, hhmm string, d int) (bool, error) {
parts := strings.Split(hhmm, ":")
// optional: be strict about two-digit values
if len(parts) != 2 {
return false, fmt.Errorf("invalid time string %q", hhmm)
}
h, err := strconv.Atoi(parts[0])
if err != nil {
return false, err
}
if h < 0 || h >= 60 {
return false, fmt.Errorf("invalid hour value %s", parts[0])
}
m, err := strconv.Atoi(parts[1])
if err != nil {
return false, err
}
if m < 0 || m >= 60 {
return false, fmt.Errorf("invalid minute value %s", parts[1])
}
var wd []time.Weekday
for _, s := range days {
w, err := parseWeekday(s)
if err != nil {
return false, err
}
wd = append(wd, w)
}
ok := startOK(when, wd, h, m, d)
return ok, nil
}
// parseWeekday handles weekday strings.
//
// Ideally we'd use time.Parse for this, as it already has
// these in it, but they are not exported in usable form.
func parseWeekday(s string) (time.Weekday, error) {
strToWeekday := map[string]time.Weekday{
"Sunday": time.Sunday,
"Monday": time.Monday,
"Tuesday": time.Tuesday,
"Wednesday": time.Wednesday,
"Thursday": time.Thursday,
"Friday": time.Friday,
"Saturday": time.Saturday,
}
if v, ok := strToWeekday[s]; ok {
return v, nil
}
return time.Sunday, fmt.Errorf("invalid day-of-week %q", s)
}
// tests should be converted to real tests and put in
// a separate file.
func tests() {
okDays := []string{"Sunday", "Wednesday"}
okStart := "04:00"
okDuration := 2 // hours
tfmt := "Mon Jan 2 15:04:05 2006"
t1 := "Sat Sep 5 04:30:00 2020" // time OK, day not
t2 := "Sun Sep 6 04:30:00 2020" // time OK, day OK
check := func(s string, expect bool) {
when, err := time.Parse(tfmt, s)
if err != nil {
panic(err)
}
result, err := startOKStr(when, okDays, okStart, okDuration)
if err != nil {
panic(err)
}
if result != expect {
fmt.Printf("fail: expected %v for %q\n", expect, s)
}
}
check(t1, false)
check(t2, true)
fmt.Println("2 tests run")
}
func main() {
tests()
}
I have cmd prompt,In which stdin accept only string, but once i receive the string need to convert to float. when someone mistakenly enter "0..1" instead of 0.1, I need check it and show error info.
msg := "enter the rate eg:{0.1}"
rate, err := RatePrompt(msg)
if err != nil {
fmt.Println("something went while entering rate, please re-enter")
}
func RatePrompt(cmrmsg string) (price string, err error) {
fmt.Println(" ")
scanner := bufio.NewScanner(os.Stdin)
scanner.Scan()
price := scanner.Text()
return price, nil
}
//check for string contains multiple dot
rate, err := RatePrompt(msg)
if err != nil {
fmt.Println("something went while entering
rate, please re-enter")else{
///check for string contains multiple dot
}
}
checking for multiple dot in string value, if multiple dot present throw error
If you are just checking for number use this instead of dot check
i, err := strconv.ParseFloat(elem, 64)
if err != nil {
numbers = append(numbers, i)
}
I'm writing some web service which supposed to receive an xml file from user, read it and save data to database
This file is gzipped and encoded in UTF-16. So i have to ungzip it, save xml to a file (for future purposes). Next i have to read file into a string, decode it to UTF-8 and kind of xml.Unmarshal([]byte(xmlString), &report)
Currently without saving it into a database
On my local machine i've realized that processing of one request takes about 30% of my CPU and about 300ms of time. For one request looks like okay. But i made script which simultaneously fires 100 requests (via curl ) and i saw that CPU usage is up to 100% and time for one request increased to 2sec
What i wanted to ask is: should i worry about it or maybe on a real web server things are going to be ok? Or maybe i'm doing smth wrong
Here is the code:
func Parse(filename string) Report {
xmlString := getXml(filename)
report := Report{}
xml.Unmarshal([]byte(xmlString), &report)
return report
}
func getXml(filename string) string {
b, err := ioutil.ReadFile(filename)
if err != nil {
fmt.Println("Error opening file:", err)
}
s, err := decodeUTF16(b)
if err != nil {
panic(err)
}
pattern := `<?xml version="1.0" encoding="UTF-16"?>`
res := strings.Replace(s, pattern, "", 1)
return res
}
func decodeUTF16(b []byte) (string, error) {
if len(b)%2 != 0 {
return "", fmt.Errorf("Must have even length byte slice")
}
u16s := make([]uint16, 1)
ret := &bytes.Buffer{}
b8buf := make([]byte, 4)
lb := len(b)
for i := 0; i < lb; i += 2 {
u16s[0] = uint16(b[i]) + (uint16(b[i+1]) << 8)
r := utf16.Decode(u16s)
n := utf8.EncodeRune(b8buf, r[0])
ret.Write(b8buf[:n])
}
return ret.String(), nil
}
Please ask if i forgot something important
I'm quite new to Go and mainly work in C#. I am currently working on something that will be used as a command to get the next bus. Currently it does not compile because I am struggling with understanding how to use the time package in Go.
I have an array of strings formatted as times when it is scheduled and another for the minutes when it is a regular service like so (there are many more times these are just an example:
var ScheduledTimes = []string{"06:34", "06:54", "17:09", "17:19"}
var RegularTimes = []string{"05", "50"}
So what I am currently doing is getting the current time and checking if it is in regular service by doing this:
func isWithinRegularService(check time.Time) bool {
RegularStart, err := time.Parse(time.Kitchen, "10:05")
RegularEnd, err := time.Parse(time.Kitchen, "13:52")
return check.After(RegularStart) && check.Before(RegularEnd)
}
time := time.Now().UTC().Format("15:04")
if isWithinRegularService(time) { }
If it is in regular service, I will then determine what hour needs looking at (i.e this one or is the next service within the next hour)
if time.Minutes < 5 && time.Minutes >= 0 {
RegularTimes[0] = fmt.Sprintf("%s%s", time.Hour+1, RegularTimes[0])
RegularTimes[1] = fmt.Sprintf("%s%s", time.Hour+1, RegularTimes[1])
RegularTimes[2] = fmt.Sprintf("%s%s", time.Hour+1, RegularTimes[2])
RegularTimes[3] = fmt.Sprintf("%s%s", time.Hour+1, RegularTimes[3])
} else {
RegularTimes[0] = fmt.Sprintf("%s%s", time.Hour, RegularTimes[0])
RegularTimes[1] = fmt.Sprintf("%s%s", time.Hour, RegularTimes[1])
RegularTimes[2] = fmt.Sprintf("%s%s", time.Hour, RegularTimes[2])
RegularTimes[3] = fmt.Sprintf("%s%s", time.Hour, RegularTimes[3])
}
Before I pass that array to another func to give me the times to check between
type BusTime struct {
betweenStart string
betweenEnd string
}
func getBusTime(busTimes []array, iteration int) BusTime {
var timesToReturn BusTime
if iteration == busTimes.Count()-1 {
timesToReturn.betweenStart = busTimes[iteration]
timesToReturn.betweenEnd = busTimes[0]
} else {
timesToReturn.betweenStart = busTimes[iteration]
timesToReturn.betweenEnd = busTimes[iteration+1]
}
return timesToReturn
}
busTimes := getBusTime(quaylinkRegularTimes, i)
And lastly I then check if the time provided is between the times to compare:
check.After(start) && check.Before(end)
That is about it for this project. If it is not with regular service it will do the exact same but skip out determining what hour to look at.
Currently this does not build because I am using strings where I should be using times, I was hoping to get some guidance, some examples, and corrections on how to use times correctly to achieve what I'm looking to do. So far I believe my logic to the way this will flow is correct, but I'm stuck getting it to compile.
Since time.Time is a particular instant, at a particular location, using it for arbitrary clock time without a day or timezone can be awkward. What you're really looking for is the duration since 00:00, so a time.Duration makes more sense. You could even use your own type based on minutes since midnight for example, but if you use a time.Duration you'll be able to compose your times with time.Time more easily.
Here's an example function to parse your clock times, and minutes into a time.Duration
func ParseTime(t string) (time.Duration, error) {
var mins, hours int
var err error
parts := strings.SplitN(t, ":", 2)
switch len(parts) {
case 1:
mins, err = strconv.Atoi(parts[0])
if err != nil {
return 0, err
}
case 2:
hours, err = strconv.Atoi(parts[0])
if err != nil {
return 0, err
}
mins, err = strconv.Atoi(parts[1])
if err != nil {
return 0, err
}
default:
return 0, fmt.Errorf("invalid time: %s", t)
}
if mins > 59 || mins < 0 || hours > 23 || hours < 0 {
return 0, fmt.Errorf("invalid time: %s", t)
}
return time.Duration(hours)*time.Hour + time.Duration(mins)*time.Minute, nil
}
You can also combine this with your own type, using the same underlying int64 type, so that you can easily format the time.Duration and add your own methods. It's up to you if returning a Time or a time.Duration from ParseTime is more convenient. The two here are directly convertible.
type Time int64
func (t Time) Hours() int {
return int(time.Duration(t) / time.Hour)
}
func (t Time) Minutes() int {
return int((time.Duration(t) % time.Hour) / time.Minute)
}
func (t Time) String() string {
return fmt.Sprintf("%02d:%02d", t.Hours(), t.Minutes())
}
You could combine these like so: http://play.golang.org/p/E679m2wlUO