I have an int64 like:
1502712864232
Which is the result of a REST GET to a service. I can convert it to a string easily enough. It is a Unixnano timestamp.
What I really need is to convert it to a string which is related to a timezone like "Europe/London". Such as:-
"14/08/2017, 13:14:24"
Such as produced by this handy utility:
http://www.freeformatter.com/epoch-timestamp-to-date-converter.html
Would very much appreciate any assistance.
==> Update.
Thanks to #evanmcdonnal for such a useful answer. Much appreciated.
Turns out that the data I had was not UnixNano at all (sorry) it was milliseconds from Epoch. Source is a Jenkins timestamp....
So... I wrote the following helper function to get what I need:
// Arg 1 is an int64 representing the millis since Epoch
// Arg 2 is a timezome. Eg: "Europe/London"
// Arg 3 is an int relating to the formatting of the returned string
// Needs the time package. Obviously.
func getFormattedTimeFromEpochMillis(z int64, zone string, style int) string {
var x string
secondsSinceEpoch := z / 1000
unixTime := time.Unix(secondsSinceEpoch, 0)
timeZoneLocation, err := time.LoadLocation(zone)
if err != nil {
fmt.Println("Error loading timezone:", err)
}
timeInZone := unixTime.In(timeZoneLocation)
switch style {
case 1:
timeInZoneStyleOne := timeInZone.Format("Mon Jan 2 15:04:05")
//Mon Aug 14 13:36:02
return timeInZoneStyleOne
case 2:
timeInZoneStyleTwo := timeInZone.Format("02-01-2006 15:04:05")
//14-08-2017 13:36:02
return timeInZoneStyleTwo
case 3:
timeInZoneStyleThree := timeInZone.Format("2006-02-01 15:04:05")
//2017-14-08 13:36:02
return timeInZoneStyleThree
}
return x
}
Rather than converting this to a string, you'll want to convert it to a time.Time and from there to a string. You can use the handy Unix method to get a Time object back for that time stamp.
import "time"
import "fmt"
t := time.Unix(0, 1502712864232)
fmt.Println(t.Format("02/01/2006, 15:04:05"))
Edit: added format to the println - note, testing your unix stamp in go playground, that value is neither nano seconds nor seconds, in both cases the time value produced is way off of what it should be. The code above still demonstrates the basic idea of what you want to do but it seems an additional step is necessary or the sample int64 you gave just does not correspond to the string you provided.
relevant docs:
https://golang.org/pkg/time/#Unix
https://golang.org/pkg/fmt/
Related
I'm parsing a cron string from AWS that looks like this cron(0 7 13 November ? 2019). Is there a clean way to go from November back to 11 using Go's built in types? The time.Month type allows mapping int to string, but there doesn't seem to be a way to do the reverse. Am I missing something? For now, I've written this to get a map[string]int that I'm using like this: monthi := getMonths()[monthName].
func getMonths() map[string]int {
m := make(map[string]int)
for i := 1; i < 13; i++ {
month := time.Month(i).String()
m[month] = i
}
return m
}
Foreword: I released this utility in github.com/icza/gox, see timex.ParseMonth().
That is currently the best approach.
Best would be to use a package level variable and populate the map only once.
And it's much cleaner and safer to do the population this way:
var months = map[string]time.Month{}
func init() {
for i := time.January; i <= time.December; i++ {
months[i.String()] = i
}
}
Testing it:
for _, s := range []string{"January", "December", "invalid"} {
m := months[s]
fmt.Println(int(m), m)
}
Output (try it on the Go Playground):
1 January
12 December
0 %!Month(0)
Note that this map has the flexibility that you may add short month names, mapping to the same month. E.g. you may also add months["Jan"] = time.January, so if your input is "Jan", you would also be able to get time.January. This could easily be done by slicing the long name, in the same loop, for example:
for i := time.January; i <= time.December; i++ {
name := i.String()
months[name] = i
months[name[:3]] = i
}
Also note that it's possible to use time.Parse() to do the parsing where the layout string is "January":
for _, s := range []string{"January", "December", "invalid"} {
t, err := time.Parse("January", s)
m := t.Month()
fmt.Println(int(m), m, err)
}
Which outputs (try it on the Go Playground):
1 January <nil>
12 December <nil>
1 January parsing time "invalid" as "January": cannot parse "invalid" as "January"
But the simple map lookup is superior to this in performance.
See similar question: Parse Weekday string into time.Weekday
How do I convert any given number which can be a int or float64 to string ?
Using strconv.FormatFloat or FormatInt I have to specify that the given number is a float or integer.
In my case it is unknown what I get.
Behaviour:
When I get a 5 it should be converted into "5" and not "5.00"
When I get a 1.23 it should be converted into "1.23" and not "1"
You may use fmt.Sprint
fmt.Sprint returns string format of any variable passed to it
Sample
package main
import (
"fmt"
)
func main() {
f := fmt.Sprint(5.03)
i := fmt.Sprint(5)
fmt.Println("float:",f,"\nint:",i)
}
play link
If you don't know what type the number you need to convert to string will be, you can just use fmt.Sprintf with the %v verb:
fmt.Sprintf("%v", 1.23) // "1.23"
fmt.Sprintf("%v", 5) // "5"
How found offset index a string in []rune using go?
I can do this work with string type.
if i := strings.Index(input[offset:], "}}"); i > 0 {print(i);}
but i need for runes.
i have a rune and want get offset index.
how can do this work with runes type in go?
example for more undrestand want need:
int offset=0//mean start from 0 (this is important for me)
string text="123456783}}56"
if i := strings.Index(text[offset:], "}}"); i > 0 {print(i);}
output of this example is : 9
but i want do this with []rune type(text variable)
may?
see my current code : https://play.golang.org/p/seImKzVpdh
tank you.
Edit #2: You again indicated a new type "meaning" of your question: you want to search a string in a []rune.
Answer: this is not supported directly in the standard library. But it's easy to implement it with 2 for loops:
func search(text []rune, what string) int {
whatRunes := []rune(what)
for i := range text {
found := true
for j := range whatRunes {
if text[i+j] != whatRunes[j] {
found = false
break
}
}
if found {
return i
}
}
return -1
}
Testing it:
value := []rune("123}456}}789")
result := search(value, "}}")
fmt.Println(result)
Output (try it on the Go Playground):
7
Edit: You updated the question indicating that you want to search runes in a string.
You may easily convert a []rune to a string using a simple type conversion:
toSearchRunes := []rune{'}', '}'}
toSearch := string(toSearchRunes)
And from there on, you can use strings.Index() as you did in your example:
if i := strings.Index(text[offset:], toSearch); i > 0 {
print(i)
}
Try it on the Go Playground.
Original answer follows:
string values in Go are stored as UTF-8 encoded bytes. strings.Index() returns you the byte position if the given substring is found.
So basically what you want is to convert this byte-position to rune-position. The unicode/utf8 package contains utility functions for telling the rune-count or rune-length of a string: utf8.RuneCountInString().
So basically you just need to pass the substring to this function:
offset := 0
text := "123456789}}56"
if i := strings.Index(text[offset:], "}}"); i > 0 {
fmt.Println("byte-pos:", i, "rune-pos:", utf8.RuneCountInString(text[offset:i]))
}
text = "世界}}世界"
if i := strings.Index(text[offset:], "}}"); i > 0 {
fmt.Println("byte-pos:", i, "rune-pos:", utf8.RuneCountInString(text[offset:i]))
}
Output (try it on the Go Playground):
byte-pos: 9 rune-pos: 9
byte-pos: 6 rune-pos: 2
Note: offset must also be a byte position, because when slicing a string like text[offset:], the index is interpreted as byte-index.
If you want to get the index of a rune, use strings.IndexRune() instead of strings.Index().
i have the following code:
I know about runes in go, i read about them a lot in the last hours i have tried to solve this...
package main
import (
"fmt"
"strconv"
)
func main() {
e := "\x002"
fmt.Println(e)
new := string(e)
i, err := strconv.Atoi(new)
if err != nil { fmt.Println(err) }
fmt.Println(i)
}
result is:
2
strconv.ParseInt: parsing "\x002": invalid syntax
0
why can't i convert the string to an integer?
Any help appreciated!
I'm not 100% sure of your goal but it looks like you want to extract the int value of the rune you get from a string containing a given character.
It looks like you want
e := "\x02"
runes := []rune(e)
i := runes[0]
fmt.Println(i) // 2
\xXXXX tries to parse it as a unicode rune, you need to skip the \ check this:
Either use :
e := "\\x002"
#or use a raw string :
e := `\x002`
edit :
Why do you think \x002 is a valid integer? do you mean 0x002?
I've got a string with milliseconds since the epoch (it came originally from a java.lang.System.currentTimeMillis() call). What's the right way to convert this string into a human readable timestamp string in Go?
Looking at the time package I see the Parse function, but the layouts all seem to be normal timezone-based times. Once into a Time object, I can use Format(Time.Stamp) to get the output I want, but I'm not clear on how to get the string into a Time object.
The format string does not support milliseconds since the epoch, so you need to parse manually. For example:
func msToTime(ms string) (time.Time, error) {
msInt, err := strconv.ParseInt(ms, 10, 64)
if err != nil {
return time.Time{}, err
}
return time.Unix(0, msInt*int64(time.Millisecond)), nil
}
Check out http://play.golang.org/p/M1dWGLT8XE to play with the example live.
2021 update: you can use UnixMilli to parse from the integer. This would improve the accepted answer to:
func msToTime(ms string) (time.Time, error) {
msInt, err := strconv.ParseInt(ms, 10, 64)
if err != nil {
return time.Time{}, err
}
return time.UnixMilli(msInt), nil
}
The accepted answer will not work for some date ranges either too far in the future or too far in the past because only a limited date range can be described using 64 bits (plus or minus 300 years from Epoch).
This will work for the entire range describable by milliseconds:
var Epoch = time.Unix(0, 0)
func ParseMillisecondUnixTimestamp(s string) (time.Time, error) {
ts, err := strconv.Atoi(s)
if err != nil {
return time.Time{}, err
}
return Epoch.Add(time.Duration(ts) * time.Millisecond), nil
}
Using time.Unix(ms/1000, 0) would do the trick.
First convert the ms-timestamp to unix-timestamp using the well known relation 1 s = 1000 ms and then use the result as first argument to the time.Unix function